/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.sysml.hops.globalopt.gdfgraph; import java.util.ArrayList; import org.apache.sysml.hops.AggUnaryOp; import org.apache.sysml.hops.DataGenOp; import org.apache.sysml.hops.Hop; import org.apache.sysml.hops.Hop.DataGenMethod; import org.apache.sysml.hops.Hop.Direction; import org.apache.sysml.hops.Hop.FileFormatTypes; import org.apache.sysml.hops.Hop.OpOp1; import org.apache.sysml.hops.UnaryOp; import org.apache.sysml.hops.rewrite.HopRewriteUtils; import org.apache.sysml.parser.Expression.DataType; import org.apache.sysml.runtime.controlprogram.Program; import org.apache.sysml.runtime.controlprogram.ProgramBlock; import org.apache.sysml.runtime.controlprogram.parfor.util.IDSequence; /** * The reason of a custom graph structure is to unify both within DAG * and cross DAG enumeration. Conceptually, we would only need interesting * properties of transient reads and could compile locally. * * Furthermore, having a global graph structure also allows for more advanced * algebraic simplification rewrites because the semantics of transient read * inputs are always available. * */ public class GDFNode { public enum NodeType{ HOP_NODE, LOOP_NODE, CROSS_BLOCK_NODE, } private static IDSequence _seqID = new IDSequence(); protected NodeType _type = null; protected long _ID = -1; //references to original program and hop dag protected Hop _hop = null; protected ProgramBlock _pb = null; //input nodes protected ArrayList<GDFNode> _inputs = null; public GDFNode() { _ID = _seqID.getNextID(); } public GDFNode( Hop hop, ProgramBlock pb, ArrayList<GDFNode> inputs ) { this(); _type = NodeType.HOP_NODE; _hop = hop; _pb = pb; _inputs = inputs; } public NodeType getNodeType() { return _type; } public long getID() { return _ID; } public Hop getHop() { return _hop; } public ProgramBlock getProgramBlock() { return _pb; } public Program getProgram() { if( _pb != null ) return _pb.getProgram(); return null; } public ArrayList<GDFNode> getInputs() { return _inputs; } public DataType getDataType() { return _hop.getDataType(); } /** * If the output or any input is a matrix we need to consider * MR configurations. This for examples excludes Literals or * any purely scalar operation. * * @return true if requires MR enumeration */ public boolean requiresMREnumeration() { //general rule: MR generation required if at least one matrix input/output boolean ret = (_hop.getDataType() == DataType.MATRIX); for( Hop c : _hop.getInput() ) ret |= (c.getDataType() == DataType.MATRIX); //special cases of CP-only operators if( _hop instanceof UnaryOp && ((UnaryOp)_hop).getOp()==OpOp1.CAST_AS_SCALAR ) //as.scalar ret = false; if( _hop instanceof DataGenOp && ((DataGenOp)_hop).getOp()==DataGenMethod.SINIT ) //matrix(str, ) ret = false; if( _hop instanceof UnaryOp && ((UnaryOp)_hop).getOp()==OpOp1.NROW ) //nrow - meta data only ret = false; if( _hop instanceof UnaryOp && ((UnaryOp)_hop).getOp()==OpOp1.NCOL ) //ncol - meta data only ret = false; return ret; } public boolean isValidInputFormatForOperation( FileFormatTypes format ) { return ( _hop instanceof UnaryOp && format!=FileFormatTypes.CSV || (_hop instanceof AggUnaryOp && ((AggUnaryOp)_hop).getDirection()==Direction.RowCol && format!=FileFormatTypes.CSV) || (HopRewriteUtils.isTransposeOperation(_hop) && format!=FileFormatTypes.CSV) || format==FileFormatTypes.BINARY ); //any op } public String explain(String deps) { String ldeps = (deps!=null) ? deps : ""; //node details if( _hop!=null ) return "Node "+ldeps+" ["+_hop.getHopID()+", "+_hop.getOpString()+"]"; else return "Node "+ldeps+" [null]"; } }