/* * 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; import java.util.ArrayList; import org.apache.sysml.hops.DataOp; import org.apache.sysml.hops.FunctionOp; import org.apache.sysml.hops.Hop.DataOpTypes; import org.apache.sysml.hops.OptimizerUtils; import org.apache.sysml.hops.globalopt.gdfgraph.GDFNode; import org.apache.sysml.hops.globalopt.gdfgraph.GDFNode.NodeType; import org.apache.sysml.lops.LopProperties.ExecType; import org.apache.sysml.parser.Expression.DataType; import org.apache.sysml.runtime.controlprogram.parfor.util.IDSequence; public class Plan { private static IDSequence _seqID = new IDSequence(); private long _ID = -1; private GDFNode _node = null; private InterestingProperties _ips = null; private RewriteConfig _conf = null; private ArrayList<Plan> _childs = null; private double _costs = -1; public Plan(GDFNode node, InterestingProperties ips, RewriteConfig rc, ArrayList<Plan> childs) { _ID = _seqID.getNextID(); _node = node; _ips = ips; _conf = rc; if( childs != null && !childs.isEmpty() ) _childs = childs; else _childs = new ArrayList<Plan>(); } public Plan( Plan p ) { _ID = _seqID.getNextID(); _node = p._node; _ips = new InterestingProperties(p._ips); _conf = new RewriteConfig(p._conf); _costs = p._costs; if( p._childs != null && !p._childs.isEmpty() ) _childs = new ArrayList<Plan>(p._childs); else _childs = new ArrayList<Plan>(); } public GDFNode getNode() { return _node; } public void addChild( Plan c ) { _childs.add(c); } public ArrayList<Plan> getChilds() { return _childs; } public InterestingProperties getInterestingProperties() { return _ips; } public RewriteConfig getRewriteConfig() { return _conf; } public void setCosts( double costs ) { _costs = costs; } public double getCosts() { return _costs; } /** * If operation is executed in MR, all input blocksizes need to match. * Note that the output blocksize can be different since we would add * additional reblocks after that operation. * * @return true if valid blocksizes in MR */ public boolean checkValidBlocksizesInMR() { boolean ret = true; ExecType CLUSTER = OptimizerUtils.isSparkExecutionMode() ? ExecType.SPARK : ExecType.MR; if( _conf.getExecType()==CLUSTER && _childs != null && _childs.size() > 1 ) { int size0 = _childs.get(0)._conf.getBlockSize(); if( size0 > 0 ) { //-1 compatible with everything for( Plan c : _childs ) ret &= ( c._conf.getBlockSize() == size0 ||c._conf.getBlockSize() <= 0 ); } } return ret; } public boolean checkValidBlocksizesTRead() { boolean ret = true; if( _node.getNodeType() == NodeType.HOP_NODE && _node.getHop() instanceof DataOp && ((DataOp)_node.getHop()).getDataOpType() == DataOpTypes.TRANSIENTREAD ) { for( Plan c : _childs ) ret &= ( _conf.getBlockSize() == c._conf.getBlockSize() ); } if( _node.getNodeType() == NodeType.CROSS_BLOCK_NODE ) { for( Plan c : _childs ) ret &= ( _conf.getBlockSize() == c._conf.getBlockSize() ); } return ret; } /** * If operation is executed in MR, only certain operations allow * all formats. In general, unary operations also allow for cell inputs. * TODO: check and test current format assumptions * * @return true if valid format in MR */ public boolean checkValidFormatInMR() { boolean ret = true; ExecType CLUSTER = OptimizerUtils.isSparkExecutionMode() ? ExecType.SPARK : ExecType.MR; if( _conf.getExecType()==CLUSTER ) { if( _childs != null ) for( Plan c : _childs ) ret &= _node.isValidInputFormatForOperation(c._conf.getFormat()); } return ret; } public boolean checkValidExecutionType() { boolean ret = true; ret &= !( _node.getHop() instanceof FunctionOp && _conf.getExecType()!=ExecType.CP ); //unnecessary, because reblock now merged into base hop //ret &= !( _node.getHop() instanceof ReblockOp && _conf.getExecType()!=ExecType.MR ); return ret; } /** * A plan is defined as preferred if its output interesting properties * match the interesting properties of all its matrix inputs. * * @return true if preferred plan */ public boolean isPreferredPlan() { boolean ret = true; for( Plan c : _childs ) if( c.getNode().getDataType()==DataType.MATRIX ) ret &= _ips.equals( c.getInterestingProperties() ); return ret; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("PLAN("+_ID+") ["); sb.append(_ips.toString()); sb.append(","); sb.append(_conf.toString()); sb.append(",{"); for( Plan c : _childs ){ sb.append(c._ID); sb.append(","); } sb.setLength(sb.length()-1); sb.append("},"); sb.append(_costs); sb.append("]"); return sb.toString(); } }