| /* |
| * 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; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.sysml.api.DMLScript; |
| import org.apache.sysml.api.DMLScript.RUNTIME_PLATFORM; |
| import org.apache.sysml.conf.ConfigurationManager; |
| import org.apache.sysml.lops.CSVReBlock; |
| import org.apache.sysml.lops.Checkpoint; |
| import org.apache.sysml.lops.Compression; |
| import org.apache.sysml.lops.Data; |
| import org.apache.sysml.lops.Lop; |
| import org.apache.sysml.lops.LopsException; |
| import org.apache.sysml.lops.ReBlock; |
| import org.apache.sysml.lops.UnaryCP; |
| import org.apache.sysml.lops.LopProperties.ExecType; |
| import org.apache.sysml.parser.Expression.DataType; |
| import org.apache.sysml.parser.Expression.ValueType; |
| import org.apache.sysml.runtime.controlprogram.LocalVariableMap; |
| import org.apache.sysml.runtime.controlprogram.caching.MatrixObject.UpdateType; |
| import org.apache.sysml.runtime.controlprogram.context.SparkExecutionContext; |
| import org.apache.sysml.runtime.controlprogram.parfor.ProgramConverter; |
| import org.apache.sysml.runtime.controlprogram.parfor.util.IDSequence; |
| import org.apache.sysml.runtime.matrix.MatrixCharacteristics; |
| import org.apache.sysml.runtime.matrix.data.MatrixBlock; |
| import org.apache.sysml.runtime.util.UtilFunctions; |
| |
| |
| public abstract class Hop |
| { |
| |
| protected static final Log LOG = LogFactory.getLog(Hop.class.getName()); |
| |
| public static final long CPThreshold = 2000; |
| protected static final boolean BREAKONSCALARS = false; |
| protected static final boolean SPLITLARGEMATRIXMULT = true; |
| |
| public enum VisitStatus { |
| DONE, |
| VISITING, |
| NOTVISITED, |
| } |
| |
| /** |
| * Optional hop interface, to be implemented by multi-threaded hops. |
| */ |
| public interface MultiThreadedHop { |
| public abstract void setMaxNumThreads( int k ); |
| public abstract int getMaxNumThreads(); |
| } |
| |
| // static variable to assign an unique ID to every hop that is created |
| private static IDSequence _seqHopID = new IDSequence(); |
| |
| protected long _ID; |
| protected String _name; |
| protected DataType _dataType; |
| protected ValueType _valueType; |
| protected VisitStatus _visited = VisitStatus.NOTVISITED; |
| protected long _dim1 = -1; |
| protected long _dim2 = -1; |
| protected long _rows_in_block = -1; |
| protected long _cols_in_block = -1; |
| protected long _nnz = -1; |
| protected UpdateType _updateType = UpdateType.COPY; |
| |
| protected ArrayList<Hop> _parent = new ArrayList<Hop>(); |
| protected ArrayList<Hop> _input = new ArrayList<Hop>(); |
| |
| protected ExecType _etype = null; //currently used exec type |
| protected ExecType _etypeForced = null; //exec type forced via platform or external optimizer |
| |
| // Estimated size for the output produced from this Hop |
| protected double _outputMemEstimate = OptimizerUtils.INVALID_SIZE; |
| |
| // Estimated size for the entire operation represented by this Hop |
| // It includes the memory required for all inputs as well as the output |
| protected double _memEstimate = OptimizerUtils.INVALID_SIZE; |
| protected double _processingMemEstimate = 0; |
| protected double _spBroadcastMemEstimate = 0; |
| |
| // indicates if there are unknowns during compilation |
| // (in that case re-complication ensures robustness and efficiency) |
| protected boolean _requiresRecompile = false; |
| |
| // indicates if the output of this hop needs to be reblocked |
| // (usually this happens on persistent reads dataops) |
| protected boolean _requiresReblock = false; |
| |
| // indicates if the output of this hop needs to be compressed |
| // (this happens on persistent reads after reblock but before checkpoint) |
| protected boolean _requiresCompression = false; |
| |
| // indicates if the output of this hop needs to be checkpointed (cached) |
| // (the default storage level for caching is not yet exposed here) |
| protected boolean _requiresCheckpoint = false; |
| |
| // indicates if the output of this hops needs to contain materialized empty blocks |
| // if those exists; otherwise only blocks w/ non-zero values are materialized |
| protected boolean _outputEmptyBlocks = true; |
| |
| private Lop _lops = null; |
| |
| protected Hop(){ |
| //default constructor for clone |
| } |
| |
| public Hop(String l, DataType dt, ValueType vt) { |
| _ID = getNextHopID(); |
| setName(l); |
| setDataType(dt); |
| setValueType(vt); |
| } |
| |
| |
| private static long getNextHopID() { |
| return _seqHopID.getNextID(); |
| } |
| |
| public long getHopID() { |
| return _ID; |
| } |
| |
| public ExecType getExecType() |
| { |
| return _etype; |
| } |
| |
| public void resetExecType() |
| { |
| _etype = null; |
| } |
| |
| /** |
| * |
| * @return |
| */ |
| public ExecType getForcedExecType() |
| { |
| return _etypeForced; |
| } |
| |
| /** |
| * |
| * @param etype |
| */ |
| public void setForcedExecType(ExecType etype) |
| { |
| _etypeForced = etype; |
| } |
| |
| /** |
| * |
| * @return |
| */ |
| public abstract boolean allowsAllExecTypes(); |
| |
| /** |
| * Defines if this operation is transpose-safe, which means that |
| * the result of op(input) is equivalent to op(t(input)). |
| * Usually, this applies to aggregate operations with fixed output |
| * dimension. Finally, this information is very useful in order to |
| * safely optimize the plan for sparse vectors, which otherwise |
| * would be (currently) always represented dense. |
| * |
| * |
| * @return |
| */ |
| public boolean isTransposeSafe() |
| { |
| //by default: its conservatively define as unsafe |
| return false; |
| } |
| |
| /** |
| * |
| */ |
| public void checkAndSetForcedPlatform() |
| { |
| if ( DMLScript.rtplatform == RUNTIME_PLATFORM.SINGLE_NODE ) |
| _etypeForced = ExecType.CP; |
| else if ( DMLScript.rtplatform == RUNTIME_PLATFORM.HADOOP ) |
| _etypeForced = ExecType.MR; |
| else if ( DMLScript.rtplatform == RUNTIME_PLATFORM.SPARK ) |
| _etypeForced = ExecType.SPARK; |
| } |
| |
| /** |
| * |
| */ |
| public void checkAndSetInvalidCPDimsAndSize() |
| { |
| if( _etype == ExecType.CP ) |
| { |
| boolean invalid = false; |
| |
| //Step 1: check dimensions of output and all inputs (INTEGER) |
| invalid |= !OptimizerUtils.isValidCPDimensions(_dim1, _dim2); |
| for( Hop in : getInput() ) |
| invalid |= !OptimizerUtils.isValidCPDimensions(in._dim1, in._dim2); |
| |
| //Step 2: check valid output and input sizes for cp (<16GB for DENSE) |
| //(if the memory estimate is smaller than max_numcells we are guaranteed to have it in sparse representation) |
| invalid |= !( OptimizerUtils.isValidCPMatrixSize(_dim1, _dim2, OptimizerUtils.getSparsity(_dim1, _dim2, _nnz)) |
| || getOutputMemEstimate() < OptimizerUtils.MAX_NUMCELLS_CP_DENSE ); |
| for( Hop in : getInput() ) |
| invalid |= !( OptimizerUtils.isValidCPMatrixSize(in._dim1, in._dim2, OptimizerUtils.getSparsity(in._dim1, in._dim2, in._nnz)) |
| || in.getOutputMemEstimate() < OptimizerUtils.MAX_NUMCELLS_CP_DENSE); |
| |
| //force exec type mr if necessary |
| if( invalid ) { |
| if( DMLScript.rtplatform == RUNTIME_PLATFORM.HYBRID ) |
| _etype = ExecType.MR; |
| else if( DMLScript.rtplatform == RUNTIME_PLATFORM.HYBRID_SPARK ) |
| _etype = ExecType.SPARK; |
| } |
| } |
| } |
| |
| public void setRequiresReblock(boolean flag) { |
| _requiresReblock = flag; |
| } |
| |
| public void setRequiresCompression(boolean flag) { |
| _requiresCompression = flag; |
| } |
| |
| public boolean requiresCompression() { |
| return _requiresCompression; |
| } |
| |
| public boolean hasMatrixInputWithDifferentBlocksizes() |
| { |
| for( Hop c : getInput() ) { |
| if( c.getDataType()==DataType.MATRIX |
| &&(getRowsInBlock() != c.getRowsInBlock() |
| || getColsInBlock() != c.getColsInBlock()) ) |
| { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| public void setOutputBlocksizes( long brlen, long bclen ) |
| { |
| setRowsInBlock( brlen ); |
| setColsInBlock( bclen ); |
| } |
| |
| public boolean requiresReblock() |
| { |
| return _requiresReblock; |
| } |
| |
| public void setRequiresCheckpoint(boolean flag) |
| { |
| _requiresCheckpoint = flag; |
| } |
| |
| public boolean requiresCheckpoint() |
| { |
| return _requiresCheckpoint; |
| } |
| |
| |
| /** |
| * |
| * @throws HopsException |
| */ |
| public void constructAndSetLopsDataFlowProperties() |
| throws HopsException |
| { |
| //Step 1: construct reblock lop if required (output of hop) |
| constructAndSetReblockLopIfRequired(); |
| |
| //Step 2: construct compression lop if required |
| constructAndSetCompressionLopIfRequired(); |
| |
| //Step 3: construct checkpoint lop if required (output of hop or reblock) |
| constructAndSetCheckpointLopIfRequired(); |
| } |
| |
| /** |
| * |
| * @throws HopsException |
| */ |
| private void constructAndSetReblockLopIfRequired() |
| throws HopsException |
| { |
| //determine execution type |
| ExecType et = ExecType.CP; |
| if( DMLScript.rtplatform != RUNTIME_PLATFORM.SINGLE_NODE |
| && !(getDataType()==DataType.SCALAR) ) |
| { |
| et = OptimizerUtils.isSparkExecutionMode() ? ExecType.SPARK : ExecType.MR; |
| } |
| |
| //add reblock lop to output if required |
| if( _requiresReblock && et != ExecType.CP ) |
| { |
| Lop input = getLops(); |
| Lop reblock = null; |
| |
| try |
| { |
| if( (this instanceof DataOp // CSV |
| && ((DataOp)this).getDataOpType() == DataOpTypes.PERSISTENTREAD |
| && ((DataOp)this).getInputFormatType() == FileFormatTypes.CSV ) |
| || (this instanceof ParameterizedBuiltinOp |
| && ((ParameterizedBuiltinOp)this).getOp() == ParamBuiltinOp.TRANSFORM) ) |
| { |
| reblock = new CSVReBlock( input, getRowsInBlock(), getColsInBlock(), |
| getDataType(), getValueType(), et); |
| } |
| else //TEXT / MM / BINARYBLOCK / BINARYCELL |
| { |
| reblock = new ReBlock( input, getRowsInBlock(), getColsInBlock(), |
| getDataType(), getValueType(), _outputEmptyBlocks, et); |
| } |
| } |
| catch( LopsException ex ) { |
| throw new HopsException(ex); |
| } |
| |
| setOutputDimensions( reblock ); |
| setLineNumbers( reblock ); |
| setLops( reblock ); |
| } |
| } |
| |
| /** |
| * |
| * @throws HopsException |
| */ |
| @SuppressWarnings("unused") //see CHECKPOINT_SPARSE_CSR |
| private void constructAndSetCheckpointLopIfRequired() |
| throws HopsException |
| { |
| //determine execution type |
| ExecType et = ExecType.CP; |
| if( OptimizerUtils.isSparkExecutionMode() |
| && getDataType()!=DataType.SCALAR ) |
| { |
| //conditional checkpoint based on memory estimate in order to |
| //(1) avoid unnecessary persist and unpersist calls, and |
| //(2) avoid unnecessary creation of spark context (incl executors) |
| if( OptimizerUtils.isHybridExecutionMode() |
| && !OptimizerUtils.exceedsCachingThreshold(getDim2(), _outputMemEstimate) |
| || _etypeForced == ExecType.CP ) |
| { |
| et = ExecType.CP; |
| } |
| else //default case |
| { |
| et = ExecType.SPARK; |
| } |
| } |
| |
| //add checkpoint lop to output if required |
| if( _requiresCheckpoint && et != ExecType.CP ) |
| { |
| try |
| { |
| //investigate need for serialized storage of large sparse matrices |
| //(compile- instead of runtime-level for better debugging) |
| boolean serializedStorage = false; |
| if( getDataType()==DataType.MATRIX && dimsKnown(true) && !Checkpoint.CHECKPOINT_SPARSE_CSR ) { |
| double matrixPSize = OptimizerUtils.estimatePartitionedSizeExactSparsity(_dim1, _dim2, _rows_in_block, _cols_in_block, _nnz); |
| double dataCache = SparkExecutionContext.getDataMemoryBudget(true, true); |
| serializedStorage = (MatrixBlock.evalSparseFormatInMemory(_dim1, _dim2, _nnz) |
| && matrixPSize > dataCache ); //sparse in-memory does not fit in agg mem |
| } |
| else if( !dimsKnown(true) ) { |
| setRequiresRecompile(); |
| } |
| |
| //construct checkpoint w/ right storage level |
| Lop input = getLops(); |
| Lop chkpoint = new Checkpoint(input, getDataType(), getValueType(), |
| serializedStorage ? Checkpoint.getSerializeStorageLevelString() : |
| Checkpoint.getDefaultStorageLevelString() ); |
| |
| setOutputDimensions( chkpoint ); |
| setLineNumbers( chkpoint ); |
| setLops( chkpoint ); |
| } |
| catch( LopsException ex ) { |
| throw new HopsException(ex); |
| } |
| } |
| } |
| |
| /** |
| * |
| * @throws HopsException |
| */ |
| private void constructAndSetCompressionLopIfRequired() |
| throws HopsException |
| { |
| //determine execution type |
| ExecType et = ExecType.CP; |
| if( OptimizerUtils.isSparkExecutionMode() |
| && getDataType()!=DataType.SCALAR ) |
| { |
| //conditional checkpoint based on memory estimate in order to avoid unnecessary |
| //persist and unpersist calls (4x the memory budget is conservative) |
| if( OptimizerUtils.isHybridExecutionMode() |
| && 2*_outputMemEstimate < OptimizerUtils.getLocalMemBudget() |
| || _etypeForced == ExecType.CP ) |
| { |
| et = ExecType.CP; |
| } |
| else //default case |
| { |
| et = ExecType.SPARK; |
| } |
| } |
| |
| //add reblock lop to output if required |
| if( _requiresCompression ) |
| { |
| try |
| { |
| Lop compress = new Compression(getLops(), getDataType(), getValueType(), et); |
| setOutputDimensions( compress ); |
| setLineNumbers( compress ); |
| setLops( compress ); |
| } |
| catch( LopsException ex ) { |
| throw new HopsException(ex); |
| } |
| } |
| } |
| |
| |
| /** |
| * |
| * @param inputPos |
| * @return |
| * @throws HopsException |
| * @throws LopsException |
| */ |
| public static Lop createOffsetLop( Hop hop, boolean repCols ) |
| throws HopsException, LopsException |
| { |
| Lop offset = null; |
| |
| if( ConfigurationManager.isDynamicRecompilation() && hop.dimsKnown() ) |
| { |
| // If dynamic recompilation is enabled and dims are known, we can replace the ncol with |
| // a literal in order to increase the piggybacking potential. This is safe because append |
| // is always marked for recompilation and hence, we have propagated the exact dimensions. |
| offset = Data.createLiteralLop(ValueType.INT, String.valueOf(repCols ? hop.getDim2() : hop.getDim1())); |
| } |
| else |
| { |
| offset = new UnaryCP(hop.constructLops(), |
| repCols ? UnaryCP.OperationTypes.NCOL : UnaryCP.OperationTypes.NROW, |
| DataType.SCALAR, ValueType.INT); |
| } |
| |
| offset.getOutputParameters().setDimensions(0, 0, 0, 0, -1); |
| offset.setAllPositions(hop.getBeginLine(), hop.getBeginColumn(), hop.getEndLine(), hop.getEndColumn()); |
| |
| return offset; |
| } |
| |
| public void setOutputEmptyBlocks(boolean flag) |
| { |
| _outputEmptyBlocks = flag; |
| } |
| |
| public boolean isOutputEmptyBlocks() |
| { |
| return _outputEmptyBlocks; |
| } |
| |
| /** |
| * Returns the memory estimate for the output produced from this Hop. |
| * It must be invoked only within Hops. From outside Hops, one must |
| * only use getMemEstimate(), which gives memory required to store |
| * all inputs and the output. |
| * |
| * @return |
| */ |
| protected double getOutputSize() |
| { |
| return _outputMemEstimate; |
| } |
| |
| /** |
| * |
| * @return |
| */ |
| protected double getInputSize() |
| { |
| double sum = 0; |
| int len = _input.size(); |
| |
| for( int i=0; i<len; i++ ) //for all inputs |
| { |
| Hop hi = _input.get(i); |
| double hmout = hi.getOutputMemEstimate(); |
| |
| if( hmout > 1024*1024 ) {//for relevant sizes |
| //check if already included in estimate (if an input is used |
| //multiple times it is still only required once in memory) |
| //(not that this check benefits from common subexpression elimination) |
| boolean flag = false; |
| for( int j=0; j<i; j++ ) |
| flag |= (hi == _input.get(j)); |
| hmout = flag ? 0 : hmout; |
| } |
| |
| sum += hmout; |
| } |
| |
| //for(Hop h : _input ) { |
| // sum += h._outputMemEstimate; |
| //} |
| |
| return sum; |
| } |
| |
| /** |
| * |
| * @return |
| */ |
| protected double getInputOutputSize() |
| { |
| double sum = 0; |
| sum += _outputMemEstimate; |
| sum += _processingMemEstimate; |
| sum += getInputSize(); |
| |
| return sum; |
| } |
| |
| /** |
| * |
| * @param pos |
| * @return |
| */ |
| protected double getInputSize( int pos ){ |
| double ret = 0; |
| if( _input.size()>pos ) |
| ret = _input.get(pos)._outputMemEstimate; |
| return ret; |
| } |
| |
| protected double getIntermediateSize() { |
| return _processingMemEstimate; |
| } |
| |
| /** |
| * NOTES: |
| * * Purpose: Whenever the output dimensions / sparsity of a hop are unknown, this hop |
| * should store its worst-case output statistics (if known) in that table. Subsequent |
| * hops can then |
| * * Invocation: Intended to be called for ALL root nodes of one Hops DAG with the same |
| * (initially empty) memo table. |
| * |
| * @param memo |
| * @return |
| */ |
| public double getMemEstimate() |
| { |
| if ( OptimizerUtils.isMemoryBasedOptLevel() ) { |
| if ( ! isMemEstimated() ) { |
| //LOG.warn("Nonexisting memory estimate - reestimating w/o memo table."); |
| computeMemEstimate( new MemoTable() ); |
| } |
| return _memEstimate; |
| } |
| else { |
| return OptimizerUtils.INVALID_SIZE; |
| } |
| } |
| |
| /** |
| * Returns memory estimate in bytes |
| * |
| * @param mem |
| */ |
| public void setMemEstimate( double mem ) |
| { |
| _memEstimate = mem; |
| } |
| |
| public void clearMemEstimate() |
| { |
| _memEstimate = OptimizerUtils.INVALID_SIZE; |
| } |
| |
| public boolean isMemEstimated() |
| { |
| return (_memEstimate != OptimizerUtils.INVALID_SIZE); |
| } |
| |
| //wrappers for meaningful public names to memory estimates. |
| |
| public double getInputMemEstimate() |
| { |
| return getInputSize(); |
| } |
| |
| public double getOutputMemEstimate() |
| { |
| return getOutputSize(); |
| } |
| |
| public double getIntermediateMemEstimate() |
| { |
| return getIntermediateSize(); |
| } |
| |
| public double getSpBroadcastSize() |
| { |
| return _spBroadcastMemEstimate; |
| } |
| |
| /** |
| * Computes the estimate of memory required to store the input/output of this hop in memory. |
| * This is the default implementation (orchestration of hop-specific implementation) |
| * that should suffice for most hops. If a hop requires more control, this method should |
| * be overwritten with awareness of (1) output estimates, and (2) propagation of worst-case |
| * matrix characteristics (dimensions, sparsity). |
| * |
| * TODO remove memo table and, on constructor refresh, inference in refresh, single compute mem, |
| * maybe general computeMemEstimate, flags to indicate if estimate or not. |
| * |
| * @return computed estimate |
| */ |
| public void computeMemEstimate( MemoTable memo ) |
| { |
| long[] wstats = null; |
| |
| //////// |
| //Step 1) Compute hop output memory estimate (incl size inference) |
| |
| switch( getDataType() ) |
| { |
| case SCALAR: |
| { |
| //memory estimate always known |
| if( getValueType()== ValueType.DOUBLE) //default case |
| _outputMemEstimate = OptimizerUtils.DOUBLE_SIZE; |
| else //literalops, dataops |
| _outputMemEstimate = computeOutputMemEstimate( _dim1, _dim2, _nnz ); |
| break; |
| } |
| case FRAME: |
| case MATRIX: |
| { |
| //1a) mem estimate based on exactly known dimensions and sparsity |
| if( dimsKnown(true) ) { |
| //nnz always exactly known (see dimsKnown(true)) |
| _outputMemEstimate = computeOutputMemEstimate( _dim1, _dim2, _nnz ); |
| } |
| //1b) infer output statistics and mem estimate based on these statistics |
| else if( memo.hasInputStatistics(this) ) |
| { |
| //infer the output stats |
| wstats = inferOutputCharacteristics(memo); |
| |
| if( wstats != null ) { |
| //use worst case characteristics to estimate mem |
| long lnnz = ((wstats[2]>=0)?wstats[2]:wstats[0]*wstats[1]); |
| _outputMemEstimate = computeOutputMemEstimate( wstats[0], wstats[1], lnnz ); |
| |
| //propagate worst-case estimate |
| memo.memoizeStatistics(getHopID(), wstats[0], wstats[1], wstats[2]); |
| } |
| else if( dimsKnown() ) { |
| //nnz unknown, estimate mem as dense |
| long lnnz = _dim1*_dim2; |
| _outputMemEstimate = computeOutputMemEstimate( _dim1, _dim2, lnnz ); |
| } |
| else { |
| //unknown output size |
| _outputMemEstimate = OptimizerUtils.DEFAULT_SIZE; |
| } |
| } |
| //1c) mem estimate based on exactly known dimensions and unknown sparsity |
| //(required e.g., for datagenops w/o any input statistics) |
| else if( dimsKnown() ) { |
| //nnz unknown, estimate mem as dense |
| long lnnz = _dim1*_dim2; |
| _outputMemEstimate = computeOutputMemEstimate( _dim1, _dim2, lnnz ); |
| } |
| //1d) fallback: unknown output size |
| else { |
| _outputMemEstimate = OptimizerUtils.DEFAULT_SIZE; |
| } |
| |
| break; |
| } |
| case OBJECT: |
| case UNKNOWN: |
| { |
| //memory estimate always unknown |
| _outputMemEstimate = OptimizerUtils.DEFAULT_SIZE; |
| break; |
| } |
| } |
| |
| //////// |
| //Step 2) Compute hop intermediate memory estimate |
| |
| //note: ensure consistency w/ step 1 (for simplified debugging) |
| |
| if( dimsKnown(true) ) { //incl scalar output |
| //nnz always exactly known (see dimsKnown(true)) |
| _processingMemEstimate = computeIntermediateMemEstimate( _dim1, _dim2, _nnz ); |
| } |
| else if( wstats!=null ) { |
| //use worst case characteristics to estimate mem |
| long lnnz = ((wstats[2]>=0)?wstats[2]:wstats[0]*wstats[1]); |
| _processingMemEstimate = computeIntermediateMemEstimate( wstats[0], wstats[1], lnnz ); |
| } |
| else if( dimsKnown() ){ |
| //nnz unknown, estimate mem as dense |
| long lnnz = _dim1 * _dim2; |
| _processingMemEstimate = computeIntermediateMemEstimate(_dim1, _dim2, lnnz); |
| } |
| |
| |
| //////// |
| //Step 3) Compute final hop memory estimate |
| |
| //final estimate (sum of inputs/intermediates/output) |
| _memEstimate = getInputOutputSize(); |
| } |
| |
| |
| /** |
| * Computes the hop-specific output memory estimate in bytes. Should be 0 if not |
| * applicable. |
| * |
| * @param dim1 |
| * @param dim2 |
| * @param nnz |
| * @return |
| */ |
| protected abstract double computeOutputMemEstimate( long dim1, long dim2, long nnz ); |
| |
| /** |
| * Computes the hop-specific intermediate memory estimate in bytes. Should be 0 if not |
| * applicable. |
| * |
| * @param dim1 |
| * @param dim2 |
| * @param nnz |
| * @return |
| */ |
| protected abstract double computeIntermediateMemEstimate( long dim1, long dim2, long nnz ); |
| |
| /** |
| * Computes the output matrix characteristics (rows, cols, nnz) based on worst-case output |
| * and/or input estimates. Should return null if dimensions are unknown. |
| * |
| * @param memo |
| * @return |
| */ |
| protected abstract long[] inferOutputCharacteristics( MemoTable memo ); |
| |
| |
| |
| /** |
| * This function is used only for sanity check. |
| * Returns true if estimates for all the hops in the DAG rooted at the current |
| * hop are computed. Returns false if any of the hops have INVALID estimate. |
| * |
| * @return |
| */ |
| public boolean checkEstimates() { |
| boolean childStatus = true; |
| for (Hop h : this.getInput()) |
| childStatus = childStatus && h.checkEstimates(); |
| return childStatus && (_memEstimate != OptimizerUtils.INVALID_SIZE); |
| } |
| |
| /** |
| * Recursively computes memory estimates for all the Hops in the DAG rooted at the |
| * current hop pointed by <code>this</code>. |
| * |
| */ |
| public void refreshMemEstimates( MemoTable memo ) { |
| if (getVisited() == VisitStatus.DONE) |
| return; |
| for (Hop h : this.getInput()) |
| h.refreshMemEstimates( memo ); |
| this.computeMemEstimate( memo ); |
| this.setVisited(VisitStatus.DONE); |
| } |
| |
| /** |
| * This method determines the execution type (CP, MR) based ONLY on the |
| * estimated memory footprint required for this operation, which includes |
| * memory for all inputs and the output represented by this Hop. |
| * |
| * It is used when <code>OptimizationType = MEMORY_BASED</code>. |
| * This optimization schedules an operation to CP whenever inputs+output |
| * fit in memory -- note that this decision MAY NOT be optimal in terms of |
| * execution time. |
| * |
| * @return |
| */ |
| protected ExecType findExecTypeByMemEstimate() { |
| ExecType et = null; |
| char c = ' '; |
| if ( getMemEstimate() < OptimizerUtils.getLocalMemBudget() ) { |
| et = ExecType.CP; |
| } |
| else { |
| if( DMLScript.rtplatform == DMLScript.RUNTIME_PLATFORM.HYBRID ) |
| et = ExecType.MR; |
| else if( DMLScript.rtplatform == DMLScript.RUNTIME_PLATFORM.HYBRID_SPARK ) |
| et = ExecType.SPARK; |
| |
| c = '*'; |
| } |
| |
| if (LOG.isDebugEnabled()){ |
| String s = String.format(" %c %-5s %-8s (%s,%s) %s", c, getHopID(), getOpString(), OptimizerUtils.toMB(_outputMemEstimate), OptimizerUtils.toMB(_memEstimate), et); |
| //System.out.println(s); |
| LOG.debug(s); |
| } |
| |
| return et; |
| } |
| |
| public ArrayList<Hop> getParent() { |
| return _parent; |
| } |
| |
| public ArrayList<Hop> getInput() { |
| return _input; |
| } |
| |
| /** |
| * Create bidirectional links |
| * |
| * @param h |
| */ |
| public void addInput( Hop h ) |
| { |
| _input.add(h); |
| h._parent.add(this); |
| } |
| |
| public long getRowsInBlock() { |
| return _rows_in_block; |
| } |
| |
| public void setRowsInBlock(long rowsInBlock) { |
| _rows_in_block = rowsInBlock; |
| } |
| |
| public long getColsInBlock() { |
| return _cols_in_block; |
| } |
| |
| public void setColsInBlock(long colsInBlock) { |
| _cols_in_block = colsInBlock; |
| } |
| |
| public void setNnz(long nnz){ |
| _nnz = nnz; |
| } |
| |
| public long getNnz(){ |
| return _nnz; |
| } |
| |
| public void setUpdateType(UpdateType update){ |
| _updateType = update; |
| } |
| |
| public UpdateType getUpdateType(){ |
| return _updateType; |
| } |
| |
| public abstract Lop constructLops() |
| throws HopsException, LopsException; |
| |
| protected abstract ExecType optFindExecType() |
| throws HopsException; |
| |
| public abstract String getOpString(); |
| |
| protected boolean isVector() { |
| return (dimsKnown() && (_dim1 == 1 || _dim2 == 1) ); |
| } |
| |
| protected boolean areDimsBelowThreshold() { |
| return (dimsKnown() && _dim1 <= Hop.CPThreshold && _dim2 <= Hop.CPThreshold ); |
| } |
| |
| public boolean dimsKnown() { |
| return ( _dataType == DataType.SCALAR |
| || ((_dataType==DataType.MATRIX || _dataType==DataType.FRAME) |
| && _dim1 > 0 && _dim2 > 0) ); |
| } |
| |
| public boolean dimsKnown(boolean includeNnz) { |
| return ( _dataType == DataType.SCALAR |
| || ((_dataType==DataType.MATRIX || _dataType==DataType.FRAME) |
| && _dim1 > 0 && _dim2 > 0 && ((includeNnz)? _nnz>=0 : true))); |
| } |
| |
| public boolean dimsKnownAny() { |
| return ( _dataType == DataType.SCALAR |
| || ((_dataType==DataType.MATRIX || _dataType==DataType.FRAME) |
| && (_dim1 > 0 || _dim2 > 0)) ); |
| } |
| |
| public static void resetVisitStatus( ArrayList<Hop> hops ) |
| { |
| if( hops != null ) |
| for( Hop hopRoot : hops ) |
| hopRoot.resetVisitStatus(); |
| } |
| |
| public void resetVisitStatus() |
| { |
| if ( getVisited() == Hop.VisitStatus.NOTVISITED ) |
| return; |
| |
| for (Hop h : this.getInput()) |
| h.resetVisitStatus(); |
| |
| setVisited(Hop.VisitStatus.NOTVISITED); |
| } |
| |
| public static void resetRecompilationFlag( ArrayList<Hop> hops, ExecType et ) |
| { |
| resetVisitStatus( hops ); |
| for( Hop hopRoot : hops ) |
| hopRoot.resetRecompilationFlag( et ); |
| } |
| |
| public static void resetRecompilationFlag( Hop hops, ExecType et ) |
| { |
| hops.resetVisitStatus(); |
| hops.resetRecompilationFlag( et ); |
| } |
| |
| private void resetRecompilationFlag( ExecType et ) |
| { |
| if( getVisited() == VisitStatus.DONE ) |
| return; |
| |
| //process child hops |
| for (Hop h : getInput()) |
| h.resetRecompilationFlag( et ); |
| |
| //reset recompile flag |
| if( et == null || getExecType() == et || getExecType()==null ) |
| _requiresRecompile = false; |
| |
| this.setVisited(VisitStatus.DONE); |
| } |
| |
| |
| /** |
| * Test and debugging only. |
| * |
| * @param h |
| * @throws HopsException |
| */ |
| public void checkParentChildPointers( ) |
| throws HopsException |
| { |
| if( getVisited() == VisitStatus.DONE ) |
| return; |
| |
| for( Hop in : getInput() ) |
| { |
| if( !in.getParent().contains(this) ) |
| throw new HopsException("Parent-Child pointers incorrect."); |
| in.checkParentChildPointers(); |
| } |
| |
| setVisited(VisitStatus.DONE); |
| } |
| |
| public void printMe() throws HopsException { |
| if (LOG.isDebugEnabled()) { |
| StringBuilder s = new StringBuilder(""); |
| s.append(getClass().getSimpleName() + " " + getHopID() + "\n"); |
| s.append(" Label: " + getName() + "; DataType: " + _dataType + "; ValueType: " + _valueType + "\n"); |
| s.append(" Parent: "); |
| for (Hop h : getParent()) { |
| s.append(h.hashCode() + "; "); |
| } |
| ; |
| s.append("\n Input: "); |
| for (Hop h : getInput()) { |
| s.append(h.getHopID() + "; "); |
| } |
| |
| s.append("\n dims [" + _dim1 + "," + _dim2 + "] blk [" + _rows_in_block + "," + _cols_in_block + "] nnz: " + _nnz + " UpdateInPlace: " + _updateType); |
| s.append(" MemEstimate = Out " + (_outputMemEstimate/1024/1024) + " MB, In&Out " + (_memEstimate/1024/1024) + " MB" ); |
| LOG.debug(s.toString()); |
| } |
| } |
| |
| public long getDim1() { |
| return _dim1; |
| } |
| |
| public void setDim1(long dim1) { |
| _dim1 = dim1; |
| } |
| |
| public long getDim2() { |
| return _dim2; |
| } |
| |
| public void setDim2(long dim2) { |
| _dim2 = dim2; |
| } |
| |
| protected void setOutputDimensions(Lop lop) |
| throws HopsException |
| { |
| lop.getOutputParameters().setDimensions( |
| getDim1(), getDim2(), getRowsInBlock(), getColsInBlock(), getNnz(), getUpdateType()); |
| } |
| |
| public Lop getLops() { |
| return _lops; |
| } |
| |
| public void setLops(Lop lops) { |
| _lops = lops; |
| } |
| |
| public VisitStatus getVisited() { |
| return _visited; |
| } |
| |
| public DataType getDataType() { |
| return _dataType; |
| } |
| |
| public void setDataType( DataType dt ) { |
| _dataType = dt; |
| } |
| |
| public void setVisited(VisitStatus visited) { |
| _visited = visited; |
| } |
| |
| public void setName(String _name) { |
| this._name = _name; |
| } |
| |
| public String getName() { |
| return _name; |
| } |
| |
| public ValueType getValueType() { |
| return _valueType; |
| } |
| |
| public void setValueType(ValueType vt) { |
| _valueType = vt; |
| } |
| |
| public enum OpOp1 { |
| NOT, ABS, SIN, COS, TAN, ASIN, ACOS, ATAN, SIGN, SQRT, LOG, EXP, |
| CAST_AS_SCALAR, CAST_AS_MATRIX, CAST_AS_FRAME, CAST_AS_DOUBLE, CAST_AS_INT, CAST_AS_BOOLEAN, |
| PRINT, EIGEN, NROW, NCOL, LENGTH, ROUND, IQM, STOP, CEIL, FLOOR, MEDIAN, INVERSE, CHOLESKY, |
| //cumulative sums, products, extreme values |
| CUMSUM, CUMPROD, CUMMIN, CUMMAX, |
| //fused ML-specific operators for performance |
| SPROP, //sample proportion: P * (1 - P) |
| SIGMOID, //sigmoid function: 1 / (1 + exp(-X)) |
| SELP, //select positive: X * (X>0) |
| LOG_NZ, //sparse-safe log; ppred(X,0,"!=")*log(X) |
| } |
| |
| // Operations that require two operands |
| public enum OpOp2 { |
| PLUS, MINUS, MULT, DIV, MODULUS, INTDIV, LESS, LESSEQUAL, GREATER, GREATEREQUAL, EQUAL, NOTEQUAL, |
| MIN, MAX, AND, OR, LOG, POW, PRINT, CONCAT, QUANTILE, INTERQUANTILE, IQM, |
| CENTRALMOMENT, COVARIANCE, CBIND, RBIND, SOLVE, MEDIAN, INVALID, |
| //fused ML-specific operators for performance |
| MINUS_NZ, //sparse-safe minus: X-(mean*ppred(X,0,!=)) |
| LOG_NZ, //sparse-safe log; ppred(X,0,"!=")*log(X,0.5) |
| MINUS1_MULT, //1-X*Y |
| }; |
| |
| // Operations that require 3 operands |
| public enum OpOp3 { |
| QUANTILE, INTERQUANTILE, CTABLE, CENTRALMOMENT, COVARIANCE, INVALID, PLUS_MULT, MINUS_MULT |
| }; |
| |
| // Operations that require 4 operands |
| public enum OpOp4 { |
| WSLOSS, //weighted sloss mm |
| WSIGMOID, //weighted sigmoid mm |
| WDIVMM, //weighted divide mm |
| WCEMM, //weighted cross entropy mm |
| WUMM, //weighted unary mm |
| INVALID |
| }; |
| |
| |
| public enum AggOp { |
| SUM, SUM_SQ, MIN, MAX, TRACE, PROD, MEAN, VAR, MAXINDEX, MININDEX |
| }; |
| |
| public enum ReOrgOp { |
| TRANSPOSE, DIAG, RESHAPE, SORT, REV |
| //Note: Diag types are invalid because for unknown sizes this would |
| //create incorrect plans (now we try to infer it for memory estimates |
| //and rewrites but the final choice is made during runtime) |
| //DIAG_V2M, DIAG_M2V, |
| }; |
| |
| public enum ConvOp { |
| MAX_POOLING, MAX_POOLING_BACKWARD, |
| DIRECT_CONV2D, DIRECT_CONV2D_BACKWARD_FILTER, DIRECT_CONV2D_BACKWARD_DATA |
| }; |
| |
| public enum DataGenMethod { |
| RAND, SEQ, SINIT, SAMPLE, INVALID |
| }; |
| |
| public enum ParamBuiltinOp { |
| INVALID, CDF, INVCDF, GROUPEDAGG, RMEMPTY, REPLACE, REXPAND, |
| TRANSFORM, TRANSFORMAPPLY, TRANSFORMDECODE, TRANSFORMMETA, |
| TOSTRING |
| }; |
| |
| /** |
| * Functions that are built in, but whose execution takes place in an |
| * external library |
| */ |
| public enum ExtBuiltInOp { |
| EIGEN, CHOLESKY |
| }; |
| |
| public enum FileFormatTypes { |
| TEXT, BINARY, MM, CSV |
| }; |
| |
| public enum DataOpTypes { |
| PERSISTENTREAD, PERSISTENTWRITE, TRANSIENTREAD, TRANSIENTWRITE, FUNCTIONOUTPUT |
| }; |
| |
| public enum Direction { |
| RowCol, Row, Col |
| }; |
| |
| protected static final HashMap<DataOpTypes, org.apache.sysml.lops.Data.OperationTypes> HopsData2Lops; |
| static { |
| HopsData2Lops = new HashMap<Hop.DataOpTypes, org.apache.sysml.lops.Data.OperationTypes>(); |
| HopsData2Lops.put(DataOpTypes.PERSISTENTREAD, org.apache.sysml.lops.Data.OperationTypes.READ); |
| HopsData2Lops.put(DataOpTypes.PERSISTENTWRITE, org.apache.sysml.lops.Data.OperationTypes.WRITE); |
| HopsData2Lops.put(DataOpTypes.TRANSIENTWRITE, org.apache.sysml.lops.Data.OperationTypes.WRITE); |
| HopsData2Lops.put(DataOpTypes.TRANSIENTREAD, org.apache.sysml.lops.Data.OperationTypes.READ); |
| } |
| |
| protected static final HashMap<Hop.AggOp, org.apache.sysml.lops.Aggregate.OperationTypes> HopsAgg2Lops; |
| static { |
| HopsAgg2Lops = new HashMap<Hop.AggOp, org.apache.sysml.lops.Aggregate.OperationTypes>(); |
| HopsAgg2Lops.put(AggOp.SUM, org.apache.sysml.lops.Aggregate.OperationTypes.KahanSum); |
| HopsAgg2Lops.put(AggOp.SUM_SQ, org.apache.sysml.lops.Aggregate.OperationTypes.KahanSumSq); |
| HopsAgg2Lops.put(AggOp.TRACE, org.apache.sysml.lops.Aggregate.OperationTypes.KahanTrace); |
| HopsAgg2Lops.put(AggOp.MIN, org.apache.sysml.lops.Aggregate.OperationTypes.Min); |
| HopsAgg2Lops.put(AggOp.MAX, org.apache.sysml.lops.Aggregate.OperationTypes.Max); |
| HopsAgg2Lops.put(AggOp.MAXINDEX, org.apache.sysml.lops.Aggregate.OperationTypes.MaxIndex); |
| HopsAgg2Lops.put(AggOp.MININDEX, org.apache.sysml.lops.Aggregate.OperationTypes.MinIndex); |
| HopsAgg2Lops.put(AggOp.PROD, org.apache.sysml.lops.Aggregate.OperationTypes.Product); |
| HopsAgg2Lops.put(AggOp.MEAN, org.apache.sysml.lops.Aggregate.OperationTypes.Mean); |
| HopsAgg2Lops.put(AggOp.VAR, org.apache.sysml.lops.Aggregate.OperationTypes.Var); |
| } |
| |
| protected static final HashMap<ReOrgOp, org.apache.sysml.lops.Transform.OperationTypes> HopsTransf2Lops; |
| static { |
| HopsTransf2Lops = new HashMap<ReOrgOp, org.apache.sysml.lops.Transform.OperationTypes>(); |
| HopsTransf2Lops.put(ReOrgOp.TRANSPOSE, org.apache.sysml.lops.Transform.OperationTypes.Transpose); |
| HopsTransf2Lops.put(ReOrgOp.REV, org.apache.sysml.lops.Transform.OperationTypes.Rev); |
| HopsTransf2Lops.put(ReOrgOp.DIAG, org.apache.sysml.lops.Transform.OperationTypes.Diag); |
| HopsTransf2Lops.put(ReOrgOp.RESHAPE, org.apache.sysml.lops.Transform.OperationTypes.Reshape); |
| HopsTransf2Lops.put(ReOrgOp.SORT, org.apache.sysml.lops.Transform.OperationTypes.Sort); |
| |
| } |
| |
| protected static final HashMap<ConvOp, org.apache.sysml.lops.ConvolutionTransform.OperationTypes> HopsConv2Lops; |
| static { |
| HopsConv2Lops = new HashMap<ConvOp, org.apache.sysml.lops.ConvolutionTransform.OperationTypes>(); |
| HopsConv2Lops.put(ConvOp.MAX_POOLING, org.apache.sysml.lops.ConvolutionTransform.OperationTypes.MAX_POOLING); |
| HopsConv2Lops.put(ConvOp.MAX_POOLING_BACKWARD, org.apache.sysml.lops.ConvolutionTransform.OperationTypes.MAX_POOLING_BACKWARD); |
| HopsConv2Lops.put(ConvOp.DIRECT_CONV2D, org.apache.sysml.lops.ConvolutionTransform.OperationTypes.DIRECT_CONV2D); |
| HopsConv2Lops.put(ConvOp.DIRECT_CONV2D_BACKWARD_FILTER, org.apache.sysml.lops.ConvolutionTransform.OperationTypes.DIRECT_CONV2D_BACKWARD_FILTER); |
| HopsConv2Lops.put(ConvOp.DIRECT_CONV2D_BACKWARD_DATA, org.apache.sysml.lops.ConvolutionTransform.OperationTypes.DIRECT_CONV2D_BACKWARD_DATA); |
| } |
| |
| protected static final HashMap<Hop.Direction, org.apache.sysml.lops.PartialAggregate.DirectionTypes> HopsDirection2Lops; |
| static { |
| HopsDirection2Lops = new HashMap<Hop.Direction, org.apache.sysml.lops.PartialAggregate.DirectionTypes>(); |
| HopsDirection2Lops.put(Direction.RowCol, org.apache.sysml.lops.PartialAggregate.DirectionTypes.RowCol); |
| HopsDirection2Lops.put(Direction.Col, org.apache.sysml.lops.PartialAggregate.DirectionTypes.Col); |
| HopsDirection2Lops.put(Direction.Row, org.apache.sysml.lops.PartialAggregate.DirectionTypes.Row); |
| |
| } |
| |
| protected static final HashMap<Hop.OpOp2, org.apache.sysml.lops.Binary.OperationTypes> HopsOpOp2LopsB; |
| static { |
| HopsOpOp2LopsB = new HashMap<Hop.OpOp2, org.apache.sysml.lops.Binary.OperationTypes>(); |
| HopsOpOp2LopsB.put(OpOp2.PLUS, org.apache.sysml.lops.Binary.OperationTypes.ADD); |
| HopsOpOp2LopsB.put(OpOp2.MINUS, org.apache.sysml.lops.Binary.OperationTypes.SUBTRACT); |
| HopsOpOp2LopsB.put(OpOp2.MULT, org.apache.sysml.lops.Binary.OperationTypes.MULTIPLY); |
| HopsOpOp2LopsB.put(OpOp2.DIV, org.apache.sysml.lops.Binary.OperationTypes.DIVIDE); |
| HopsOpOp2LopsB.put(OpOp2.MODULUS, org.apache.sysml.lops.Binary.OperationTypes.MODULUS); |
| HopsOpOp2LopsB.put(OpOp2.INTDIV, org.apache.sysml.lops.Binary.OperationTypes.INTDIV); |
| HopsOpOp2LopsB.put(OpOp2.MINUS1_MULT, org.apache.sysml.lops.Binary.OperationTypes.MINUS1_MULTIPLY); |
| HopsOpOp2LopsB.put(OpOp2.LESS, org.apache.sysml.lops.Binary.OperationTypes.LESS_THAN); |
| HopsOpOp2LopsB.put(OpOp2.LESSEQUAL, org.apache.sysml.lops.Binary.OperationTypes.LESS_THAN_OR_EQUALS); |
| HopsOpOp2LopsB.put(OpOp2.GREATER, org.apache.sysml.lops.Binary.OperationTypes.GREATER_THAN); |
| HopsOpOp2LopsB.put(OpOp2.GREATEREQUAL, org.apache.sysml.lops.Binary.OperationTypes.GREATER_THAN_OR_EQUALS); |
| HopsOpOp2LopsB.put(OpOp2.EQUAL, org.apache.sysml.lops.Binary.OperationTypes.EQUALS); |
| HopsOpOp2LopsB.put(OpOp2.NOTEQUAL, org.apache.sysml.lops.Binary.OperationTypes.NOT_EQUALS); |
| HopsOpOp2LopsB.put(OpOp2.MIN, org.apache.sysml.lops.Binary.OperationTypes.MIN); |
| HopsOpOp2LopsB.put(OpOp2.MAX, org.apache.sysml.lops.Binary.OperationTypes.MAX); |
| HopsOpOp2LopsB.put(OpOp2.AND, org.apache.sysml.lops.Binary.OperationTypes.OR); |
| HopsOpOp2LopsB.put(OpOp2.OR, org.apache.sysml.lops.Binary.OperationTypes.AND); |
| HopsOpOp2LopsB.put(OpOp2.SOLVE, org.apache.sysml.lops.Binary.OperationTypes.SOLVE); |
| HopsOpOp2LopsB.put(OpOp2.POW, org.apache.sysml.lops.Binary.OperationTypes.POW); |
| HopsOpOp2LopsB.put(OpOp2.LOG, org.apache.sysml.lops.Binary.OperationTypes.NOTSUPPORTED); |
| } |
| |
| protected static final HashMap<Hop.OpOp2, org.apache.sysml.lops.BinaryScalar.OperationTypes> HopsOpOp2LopsBS; |
| static { |
| HopsOpOp2LopsBS = new HashMap<Hop.OpOp2, org.apache.sysml.lops.BinaryScalar.OperationTypes>(); |
| HopsOpOp2LopsBS.put(OpOp2.PLUS, org.apache.sysml.lops.BinaryScalar.OperationTypes.ADD); |
| HopsOpOp2LopsBS.put(OpOp2.MINUS, org.apache.sysml.lops.BinaryScalar.OperationTypes.SUBTRACT); |
| HopsOpOp2LopsBS.put(OpOp2.MULT, org.apache.sysml.lops.BinaryScalar.OperationTypes.MULTIPLY); |
| HopsOpOp2LopsBS.put(OpOp2.DIV, org.apache.sysml.lops.BinaryScalar.OperationTypes.DIVIDE); |
| HopsOpOp2LopsBS.put(OpOp2.MODULUS, org.apache.sysml.lops.BinaryScalar.OperationTypes.MODULUS); |
| HopsOpOp2LopsBS.put(OpOp2.INTDIV, org.apache.sysml.lops.BinaryScalar.OperationTypes.INTDIV); |
| HopsOpOp2LopsBS.put(OpOp2.LESS, org.apache.sysml.lops.BinaryScalar.OperationTypes.LESS_THAN); |
| HopsOpOp2LopsBS.put(OpOp2.LESSEQUAL, org.apache.sysml.lops.BinaryScalar.OperationTypes.LESS_THAN_OR_EQUALS); |
| HopsOpOp2LopsBS.put(OpOp2.GREATER, org.apache.sysml.lops.BinaryScalar.OperationTypes.GREATER_THAN); |
| HopsOpOp2LopsBS.put(OpOp2.GREATEREQUAL, org.apache.sysml.lops.BinaryScalar.OperationTypes.GREATER_THAN_OR_EQUALS); |
| HopsOpOp2LopsBS.put(OpOp2.EQUAL, org.apache.sysml.lops.BinaryScalar.OperationTypes.EQUALS); |
| HopsOpOp2LopsBS.put(OpOp2.NOTEQUAL, org.apache.sysml.lops.BinaryScalar.OperationTypes.NOT_EQUALS); |
| HopsOpOp2LopsBS.put(OpOp2.MIN, org.apache.sysml.lops.BinaryScalar.OperationTypes.MIN); |
| HopsOpOp2LopsBS.put(OpOp2.MAX, org.apache.sysml.lops.BinaryScalar.OperationTypes.MAX); |
| HopsOpOp2LopsBS.put(OpOp2.AND, org.apache.sysml.lops.BinaryScalar.OperationTypes.AND); |
| HopsOpOp2LopsBS.put(OpOp2.OR, org.apache.sysml.lops.BinaryScalar.OperationTypes.OR); |
| HopsOpOp2LopsBS.put(OpOp2.LOG, org.apache.sysml.lops.BinaryScalar.OperationTypes.LOG); |
| HopsOpOp2LopsBS.put(OpOp2.POW, org.apache.sysml.lops.BinaryScalar.OperationTypes.POW); |
| HopsOpOp2LopsBS.put(OpOp2.PRINT, org.apache.sysml.lops.BinaryScalar.OperationTypes.PRINT); |
| } |
| |
| protected static final HashMap<Hop.OpOp2, org.apache.sysml.lops.Unary.OperationTypes> HopsOpOp2LopsU; |
| static { |
| HopsOpOp2LopsU = new HashMap<Hop.OpOp2, org.apache.sysml.lops.Unary.OperationTypes>(); |
| HopsOpOp2LopsU.put(OpOp2.PLUS, org.apache.sysml.lops.Unary.OperationTypes.ADD); |
| HopsOpOp2LopsU.put(OpOp2.MINUS, org.apache.sysml.lops.Unary.OperationTypes.SUBTRACT); |
| HopsOpOp2LopsU.put(OpOp2.MULT, org.apache.sysml.lops.Unary.OperationTypes.MULTIPLY); |
| HopsOpOp2LopsU.put(OpOp2.DIV, org.apache.sysml.lops.Unary.OperationTypes.DIVIDE); |
| HopsOpOp2LopsU.put(OpOp2.MODULUS, org.apache.sysml.lops.Unary.OperationTypes.MODULUS); |
| HopsOpOp2LopsU.put(OpOp2.INTDIV, org.apache.sysml.lops.Unary.OperationTypes.INTDIV); |
| HopsOpOp2LopsU.put(OpOp2.MINUS1_MULT, org.apache.sysml.lops.Unary.OperationTypes.MINUS1_MULTIPLY); |
| HopsOpOp2LopsU.put(OpOp2.LESSEQUAL, org.apache.sysml.lops.Unary.OperationTypes.LESS_THAN_OR_EQUALS); |
| HopsOpOp2LopsU.put(OpOp2.LESS, org.apache.sysml.lops.Unary.OperationTypes.LESS_THAN); |
| HopsOpOp2LopsU.put(OpOp2.GREATEREQUAL, org.apache.sysml.lops.Unary.OperationTypes.GREATER_THAN_OR_EQUALS); |
| HopsOpOp2LopsU.put(OpOp2.GREATER, org.apache.sysml.lops.Unary.OperationTypes.GREATER_THAN); |
| HopsOpOp2LopsU.put(OpOp2.EQUAL, org.apache.sysml.lops.Unary.OperationTypes.EQUALS); |
| HopsOpOp2LopsU.put(OpOp2.NOTEQUAL, org.apache.sysml.lops.Unary.OperationTypes.NOT_EQUALS); |
| HopsOpOp2LopsU.put(OpOp2.AND, org.apache.sysml.lops.Unary.OperationTypes.NOTSUPPORTED); |
| HopsOpOp2LopsU.put(OpOp2.OR, org.apache.sysml.lops.Unary.OperationTypes.NOTSUPPORTED); |
| HopsOpOp2LopsU.put(OpOp2.MAX, org.apache.sysml.lops.Unary.OperationTypes.MAX); |
| HopsOpOp2LopsU.put(OpOp2.MIN, org.apache.sysml.lops.Unary.OperationTypes.MIN); |
| HopsOpOp2LopsU.put(OpOp2.LOG, org.apache.sysml.lops.Unary.OperationTypes.LOG); |
| HopsOpOp2LopsU.put(OpOp2.POW, org.apache.sysml.lops.Unary.OperationTypes.POW); |
| HopsOpOp2LopsU.put(OpOp2.MINUS_NZ, org.apache.sysml.lops.Unary.OperationTypes.SUBTRACT_NZ); |
| HopsOpOp2LopsU.put(OpOp2.LOG_NZ, org.apache.sysml.lops.Unary.OperationTypes.LOG_NZ); |
| } |
| |
| protected static final HashMap<Hop.OpOp1, org.apache.sysml.lops.Unary.OperationTypes> HopsOpOp1LopsU; |
| static { |
| HopsOpOp1LopsU = new HashMap<Hop.OpOp1, org.apache.sysml.lops.Unary.OperationTypes>(); |
| HopsOpOp1LopsU.put(OpOp1.NOT, org.apache.sysml.lops.Unary.OperationTypes.NOT); |
| HopsOpOp1LopsU.put(OpOp1.ABS, org.apache.sysml.lops.Unary.OperationTypes.ABS); |
| HopsOpOp1LopsU.put(OpOp1.SIN, org.apache.sysml.lops.Unary.OperationTypes.SIN); |
| HopsOpOp1LopsU.put(OpOp1.COS, org.apache.sysml.lops.Unary.OperationTypes.COS); |
| HopsOpOp1LopsU.put(OpOp1.TAN, org.apache.sysml.lops.Unary.OperationTypes.TAN); |
| HopsOpOp1LopsU.put(OpOp1.ASIN, org.apache.sysml.lops.Unary.OperationTypes.ASIN); |
| HopsOpOp1LopsU.put(OpOp1.ACOS, org.apache.sysml.lops.Unary.OperationTypes.ACOS); |
| HopsOpOp1LopsU.put(OpOp1.ATAN, org.apache.sysml.lops.Unary.OperationTypes.ATAN); |
| HopsOpOp1LopsU.put(OpOp1.SIGN, org.apache.sysml.lops.Unary.OperationTypes.SIGN); |
| HopsOpOp1LopsU.put(OpOp1.SQRT, org.apache.sysml.lops.Unary.OperationTypes.SQRT); |
| HopsOpOp1LopsU.put(OpOp1.EXP, org.apache.sysml.lops.Unary.OperationTypes.EXP); |
| HopsOpOp1LopsU.put(OpOp1.LOG, org.apache.sysml.lops.Unary.OperationTypes.LOG); |
| HopsOpOp1LopsU.put(OpOp1.ROUND, org.apache.sysml.lops.Unary.OperationTypes.ROUND); |
| HopsOpOp1LopsU.put(OpOp1.CEIL, org.apache.sysml.lops.Unary.OperationTypes.CEIL); |
| HopsOpOp1LopsU.put(OpOp1.FLOOR, org.apache.sysml.lops.Unary.OperationTypes.FLOOR); |
| HopsOpOp1LopsU.put(OpOp1.CUMSUM, org.apache.sysml.lops.Unary.OperationTypes.CUMSUM); |
| HopsOpOp1LopsU.put(OpOp1.CUMPROD, org.apache.sysml.lops.Unary.OperationTypes.CUMPROD); |
| HopsOpOp1LopsU.put(OpOp1.CUMMIN, org.apache.sysml.lops.Unary.OperationTypes.CUMMIN); |
| HopsOpOp1LopsU.put(OpOp1.CUMMAX, org.apache.sysml.lops.Unary.OperationTypes.CUMMAX); |
| HopsOpOp1LopsU.put(OpOp1.INVERSE, org.apache.sysml.lops.Unary.OperationTypes.INVERSE); |
| HopsOpOp1LopsU.put(OpOp1.CHOLESKY, org.apache.sysml.lops.Unary.OperationTypes.CHOLESKY); |
| HopsOpOp1LopsU.put(OpOp1.CAST_AS_SCALAR, org.apache.sysml.lops.Unary.OperationTypes.NOTSUPPORTED); |
| HopsOpOp1LopsU.put(OpOp1.CAST_AS_MATRIX, org.apache.sysml.lops.Unary.OperationTypes.NOTSUPPORTED); |
| HopsOpOp1LopsU.put(OpOp1.SPROP, org.apache.sysml.lops.Unary.OperationTypes.SPROP); |
| HopsOpOp1LopsU.put(OpOp1.SIGMOID, org.apache.sysml.lops.Unary.OperationTypes.SIGMOID); |
| HopsOpOp1LopsU.put(OpOp1.SELP, org.apache.sysml.lops.Unary.OperationTypes.SELP); |
| HopsOpOp1LopsU.put(OpOp1.LOG_NZ, org.apache.sysml.lops.Unary.OperationTypes.LOG_NZ); |
| HopsOpOp1LopsU.put(OpOp1.CAST_AS_MATRIX, org.apache.sysml.lops.Unary.OperationTypes.CAST_AS_MATRIX); |
| HopsOpOp1LopsU.put(OpOp1.CAST_AS_FRAME, org.apache.sysml.lops.Unary.OperationTypes.CAST_AS_FRAME); |
| } |
| |
| protected static final HashMap<Hop.OpOp1, org.apache.sysml.lops.UnaryCP.OperationTypes> HopsOpOp1LopsUS; |
| static { |
| HopsOpOp1LopsUS = new HashMap<Hop.OpOp1, org.apache.sysml.lops.UnaryCP.OperationTypes>(); |
| HopsOpOp1LopsUS.put(OpOp1.NOT, org.apache.sysml.lops.UnaryCP.OperationTypes.NOT); |
| HopsOpOp1LopsUS.put(OpOp1.ABS, org.apache.sysml.lops.UnaryCP.OperationTypes.ABS); |
| HopsOpOp1LopsUS.put(OpOp1.SIN, org.apache.sysml.lops.UnaryCP.OperationTypes.SIN); |
| HopsOpOp1LopsUS.put(OpOp1.COS, org.apache.sysml.lops.UnaryCP.OperationTypes.COS); |
| HopsOpOp1LopsUS.put(OpOp1.TAN, org.apache.sysml.lops.UnaryCP.OperationTypes.TAN); |
| HopsOpOp1LopsUS.put(OpOp1.ASIN, org.apache.sysml.lops.UnaryCP.OperationTypes.ASIN); |
| HopsOpOp1LopsUS.put(OpOp1.ACOS, org.apache.sysml.lops.UnaryCP.OperationTypes.ACOS); |
| HopsOpOp1LopsUS.put(OpOp1.ATAN, org.apache.sysml.lops.UnaryCP.OperationTypes.ATAN); |
| HopsOpOp1LopsUS.put(OpOp1.SQRT, org.apache.sysml.lops.UnaryCP.OperationTypes.SQRT); |
| HopsOpOp1LopsUS.put(OpOp1.EXP, org.apache.sysml.lops.UnaryCP.OperationTypes.EXP); |
| HopsOpOp1LopsUS.put(OpOp1.LOG, org.apache.sysml.lops.UnaryCP.OperationTypes.LOG); |
| HopsOpOp1LopsUS.put(OpOp1.CAST_AS_SCALAR, org.apache.sysml.lops.UnaryCP.OperationTypes.CAST_AS_SCALAR); |
| HopsOpOp1LopsUS.put(OpOp1.CAST_AS_MATRIX, org.apache.sysml.lops.UnaryCP.OperationTypes.CAST_AS_MATRIX); |
| HopsOpOp1LopsUS.put(OpOp1.CAST_AS_FRAME, org.apache.sysml.lops.UnaryCP.OperationTypes.CAST_AS_FRAME); |
| HopsOpOp1LopsUS.put(OpOp1.CAST_AS_DOUBLE, org.apache.sysml.lops.UnaryCP.OperationTypes.CAST_AS_DOUBLE); |
| HopsOpOp1LopsUS.put(OpOp1.CAST_AS_INT, org.apache.sysml.lops.UnaryCP.OperationTypes.CAST_AS_INT); |
| HopsOpOp1LopsUS.put(OpOp1.CAST_AS_BOOLEAN, org.apache.sysml.lops.UnaryCP.OperationTypes.CAST_AS_BOOLEAN); |
| HopsOpOp1LopsUS.put(OpOp1.NROW, org.apache.sysml.lops.UnaryCP.OperationTypes.NROW); |
| HopsOpOp1LopsUS.put(OpOp1.NCOL, org.apache.sysml.lops.UnaryCP.OperationTypes.NCOL); |
| HopsOpOp1LopsUS.put(OpOp1.LENGTH, org.apache.sysml.lops.UnaryCP.OperationTypes.LENGTH); |
| HopsOpOp1LopsUS.put(OpOp1.PRINT, org.apache.sysml.lops.UnaryCP.OperationTypes.PRINT); |
| HopsOpOp1LopsUS.put(OpOp1.ROUND, org.apache.sysml.lops.UnaryCP.OperationTypes.ROUND); |
| HopsOpOp1LopsUS.put(OpOp1.CEIL, org.apache.sysml.lops.UnaryCP.OperationTypes.CEIL); |
| HopsOpOp1LopsUS.put(OpOp1.FLOOR, org.apache.sysml.lops.UnaryCP.OperationTypes.FLOOR); |
| HopsOpOp1LopsUS.put(OpOp1.STOP, org.apache.sysml.lops.UnaryCP.OperationTypes.STOP); |
| } |
| |
| protected static final HashMap<Hop.OpOp1, String> HopsOpOp12String; |
| static { |
| HopsOpOp12String = new HashMap<OpOp1, String>(); |
| HopsOpOp12String.put(OpOp1.ABS, "abs"); |
| HopsOpOp12String.put(OpOp1.CAST_AS_SCALAR, "castAsScalar"); |
| HopsOpOp12String.put(OpOp1.COS, "cos"); |
| HopsOpOp12String.put(OpOp1.EIGEN, "eigen"); |
| HopsOpOp12String.put(OpOp1.EXP, "exp"); |
| HopsOpOp12String.put(OpOp1.IQM, "iqm"); |
| HopsOpOp12String.put(OpOp1.MEDIAN, "median"); |
| HopsOpOp12String.put(OpOp1.LENGTH, "length"); |
| HopsOpOp12String.put(OpOp1.LOG, "log"); |
| HopsOpOp12String.put(OpOp1.NCOL, "ncol"); |
| HopsOpOp12String.put(OpOp1.NOT, "!"); |
| HopsOpOp12String.put(OpOp1.NROW, "nrow"); |
| HopsOpOp12String.put(OpOp1.PRINT, "print"); |
| HopsOpOp12String.put(OpOp1.ROUND, "round"); |
| HopsOpOp12String.put(OpOp1.SIN, "sin"); |
| HopsOpOp12String.put(OpOp1.SQRT, "sqrt"); |
| HopsOpOp12String.put(OpOp1.TAN, "tan"); |
| HopsOpOp12String.put(OpOp1.ASIN, "asin"); |
| HopsOpOp12String.put(OpOp1.ACOS, "acos"); |
| HopsOpOp12String.put(OpOp1.ATAN, "atan"); |
| HopsOpOp12String.put(OpOp1.STOP, "stop"); |
| HopsOpOp12String.put(OpOp1.INVERSE, "inv"); |
| HopsOpOp12String.put(OpOp1.SPROP, "sprop"); |
| HopsOpOp12String.put(OpOp1.SIGMOID, "sigmoid"); |
| } |
| |
| protected static final HashMap<Hop.ParamBuiltinOp, org.apache.sysml.lops.ParameterizedBuiltin.OperationTypes> HopsParameterizedBuiltinLops; |
| static { |
| HopsParameterizedBuiltinLops = new HashMap<Hop.ParamBuiltinOp, org.apache.sysml.lops.ParameterizedBuiltin.OperationTypes>(); |
| HopsParameterizedBuiltinLops.put(ParamBuiltinOp.CDF, org.apache.sysml.lops.ParameterizedBuiltin.OperationTypes.CDF); |
| HopsParameterizedBuiltinLops.put(ParamBuiltinOp.INVCDF, org.apache.sysml.lops.ParameterizedBuiltin.OperationTypes.INVCDF); |
| HopsParameterizedBuiltinLops.put(ParamBuiltinOp.RMEMPTY, org.apache.sysml.lops.ParameterizedBuiltin.OperationTypes.RMEMPTY); |
| HopsParameterizedBuiltinLops.put(ParamBuiltinOp.REPLACE, org.apache.sysml.lops.ParameterizedBuiltin.OperationTypes.REPLACE); |
| HopsParameterizedBuiltinLops.put(ParamBuiltinOp.REXPAND, org.apache.sysml.lops.ParameterizedBuiltin.OperationTypes.REXPAND); |
| HopsParameterizedBuiltinLops.put(ParamBuiltinOp.TRANSFORM, org.apache.sysml.lops.ParameterizedBuiltin.OperationTypes.TRANSFORM); |
| HopsParameterizedBuiltinLops.put(ParamBuiltinOp.TRANSFORMAPPLY, org.apache.sysml.lops.ParameterizedBuiltin.OperationTypes.TRANSFORMAPPLY); |
| HopsParameterizedBuiltinLops.put(ParamBuiltinOp.TRANSFORMDECODE, org.apache.sysml.lops.ParameterizedBuiltin.OperationTypes.TRANSFORMDECODE); |
| HopsParameterizedBuiltinLops.put(ParamBuiltinOp.TRANSFORMMETA, org.apache.sysml.lops.ParameterizedBuiltin.OperationTypes.TRANSFORMMETA); |
| HopsParameterizedBuiltinLops.put(ParamBuiltinOp.TOSTRING, org.apache.sysml.lops.ParameterizedBuiltin.OperationTypes.TOSTRING); |
| } |
| |
| protected static final HashMap<Hop.OpOp2, String> HopsOpOp2String; |
| static { |
| HopsOpOp2String = new HashMap<Hop.OpOp2, String>(); |
| HopsOpOp2String.put(OpOp2.PLUS, "+"); |
| HopsOpOp2String.put(OpOp2.MINUS, "-"); |
| HopsOpOp2String.put(OpOp2.MINUS_NZ, "-nz"); |
| HopsOpOp2String.put(OpOp2.MINUS1_MULT, "-1*"); |
| HopsOpOp2String.put(OpOp2.MULT, "*"); |
| HopsOpOp2String.put(OpOp2.DIV, "/"); |
| HopsOpOp2String.put(OpOp2.MODULUS, "%%"); |
| HopsOpOp2String.put(OpOp2.INTDIV, "%/%"); |
| HopsOpOp2String.put(OpOp2.MIN, "min"); |
| HopsOpOp2String.put(OpOp2.MAX, "max"); |
| HopsOpOp2String.put(OpOp2.LESSEQUAL, "<="); |
| HopsOpOp2String.put(OpOp2.LESS, "<"); |
| HopsOpOp2String.put(OpOp2.GREATEREQUAL, ">="); |
| HopsOpOp2String.put(OpOp2.GREATER, ">"); |
| HopsOpOp2String.put(OpOp2.EQUAL, "="); |
| HopsOpOp2String.put(OpOp2.NOTEQUAL, "!="); |
| HopsOpOp2String.put(OpOp2.OR, "|"); |
| HopsOpOp2String.put(OpOp2.AND, "&"); |
| HopsOpOp2String.put(OpOp2.LOG, "log"); |
| HopsOpOp2String.put(OpOp2.LOG_NZ, "log_nz"); |
| HopsOpOp2String.put(OpOp2.POW, "^"); |
| HopsOpOp2String.put(OpOp2.CONCAT, "concat"); |
| HopsOpOp2String.put(OpOp2.INVALID, "?"); |
| HopsOpOp2String.put(OpOp2.QUANTILE, "quantile"); |
| HopsOpOp2String.put(OpOp2.INTERQUANTILE, "interquantile"); |
| HopsOpOp2String.put(OpOp2.IQM, "IQM"); |
| HopsOpOp2String.put(OpOp2.MEDIAN, "median"); |
| HopsOpOp2String.put(OpOp2.CENTRALMOMENT, "cm"); |
| HopsOpOp2String.put(OpOp2.COVARIANCE, "cov"); |
| HopsOpOp2String.put(OpOp2.CBIND, "cbind"); |
| HopsOpOp2String.put(OpOp2.RBIND, "rbind"); |
| HopsOpOp2String.put(OpOp2.SOLVE, "solve"); |
| } |
| |
| public static String getOpOp2String( OpOp2 op ) { |
| return HopsOpOp2String.get(op); |
| } |
| |
| protected static final HashMap<Hop.OpOp3, String> HopsOpOp3String; |
| static { |
| HopsOpOp3String = new HashMap<Hop.OpOp3, String>(); |
| HopsOpOp3String.put(OpOp3.QUANTILE, "quantile"); |
| HopsOpOp3String.put(OpOp3.INTERQUANTILE, "interquantile"); |
| HopsOpOp3String.put(OpOp3.CTABLE, "ctable"); |
| HopsOpOp3String.put(OpOp3.CENTRALMOMENT, "cm"); |
| HopsOpOp3String.put(OpOp3.COVARIANCE, "cov"); |
| HopsOpOp3String.put(OpOp3.PLUS_MULT, "+*"); |
| HopsOpOp3String.put(OpOp3.MINUS_MULT, "-*"); |
| } |
| |
| protected static final HashMap<Hop.OpOp4, String> HopsOpOp4String; |
| static { |
| HopsOpOp4String = new HashMap<Hop.OpOp4, String>(); |
| HopsOpOp4String.put(OpOp4.WSLOSS, "wsloss"); |
| HopsOpOp4String.put(OpOp4.WSIGMOID, "wsigmoid"); |
| HopsOpOp4String.put(OpOp4.WCEMM, "wcemm"); |
| HopsOpOp4String.put(OpOp4.WDIVMM, "wdivmm"); |
| HopsOpOp4String.put(OpOp4.WUMM, "wumm"); |
| } |
| |
| protected static final HashMap<Hop.Direction, String> HopsDirection2String; |
| static { |
| HopsDirection2String = new HashMap<Hop.Direction, String>(); |
| HopsDirection2String.put(Direction.RowCol, "RC"); |
| HopsDirection2String.put(Direction.Col, "C"); |
| HopsDirection2String.put(Direction.Row, "R"); |
| } |
| |
| protected static final HashMap<Hop.AggOp, String> HopsAgg2String; |
| static { |
| HopsAgg2String = new HashMap<Hop.AggOp, String>(); |
| HopsAgg2String.put(AggOp.SUM, "+"); |
| HopsAgg2String.put(AggOp.SUM_SQ, "sq+"); |
| HopsAgg2String.put(AggOp.PROD, "*"); |
| HopsAgg2String.put(AggOp.MIN, "min"); |
| HopsAgg2String.put(AggOp.MAX, "max"); |
| HopsAgg2String.put(AggOp.MAXINDEX, "maxindex"); |
| HopsAgg2String.put(AggOp.MININDEX, "minindex"); |
| HopsAgg2String.put(AggOp.TRACE, "trace"); |
| HopsAgg2String.put(AggOp.MEAN, "mean"); |
| HopsAgg2String.put(AggOp.VAR, "var"); |
| } |
| |
| protected static final HashMap<Hop.ReOrgOp, String> HopsTransf2String; |
| static { |
| HopsTransf2String = new HashMap<ReOrgOp, String>(); |
| HopsTransf2String.put(ReOrgOp.TRANSPOSE, "t"); |
| HopsTransf2String.put(ReOrgOp.DIAG, "diag"); |
| HopsTransf2String.put(ReOrgOp.RESHAPE, "rshape"); |
| HopsTransf2String.put(ReOrgOp.SORT, "sort"); |
| } |
| |
| protected static final HashMap<DataOpTypes, String> HopsData2String; |
| static { |
| HopsData2String = new HashMap<Hop.DataOpTypes, String>(); |
| HopsData2String.put(DataOpTypes.PERSISTENTREAD, "PRead"); |
| HopsData2String.put(DataOpTypes.PERSISTENTWRITE, "PWrite"); |
| HopsData2String.put(DataOpTypes.TRANSIENTWRITE, "TWrite"); |
| HopsData2String.put(DataOpTypes.TRANSIENTREAD, "TRead"); |
| } |
| |
| public static boolean isFunction(OpOp2 op) |
| { |
| return op == OpOp2.MIN || op == OpOp2.MAX || |
| op == OpOp2.LOG;// || op == OpOp2.CONCAT; //concat is || in Netezza |
| } |
| |
| public static boolean isSupported(OpOp2 op) |
| { |
| return op != OpOp2.INVALID && op != OpOp2.QUANTILE && |
| op != OpOp2.INTERQUANTILE && op != OpOp2.IQM; |
| } |
| |
| public static boolean isFunction(OpOp1 op) |
| { |
| return op == OpOp1.SIN || op == OpOp1.TAN || op == OpOp1.COS || |
| op == OpOp1.ABS || op == OpOp1.EXP || op == OpOp1.LOG || |
| op == OpOp1.ROUND || op == OpOp1.SQRT; |
| } |
| |
| public static boolean isBooleanOperation(OpOp2 op) |
| { |
| return op == OpOp2.AND || op == OpOp2.EQUAL || |
| op == OpOp2.GREATER || op == OpOp2.GREATEREQUAL || |
| op == OpOp2.LESS || op == OpOp2.LESSEQUAL || |
| op == OpOp2.OR; |
| } |
| |
| /** |
| * |
| * @param op |
| * @return |
| */ |
| public static OpOp2 getOpOp2ForOuterVectorOperation(String op) |
| { |
| if( "+".equals(op) ) return OpOp2.PLUS; |
| else if( "-".equals(op) ) return OpOp2.MINUS; |
| else if( "*".equals(op) ) return OpOp2.MULT; |
| else if( "/".equals(op) ) return OpOp2.DIV; |
| else if( "%%".equals(op) ) return OpOp2.MODULUS; |
| else if( "%/%".equals(op) ) return OpOp2.INTDIV; |
| else if( "min".equals(op) ) return OpOp2.MIN; |
| else if( "max".equals(op) ) return OpOp2.MAX; |
| else if( "<=".equals(op) ) return OpOp2.LESSEQUAL; |
| else if( "<".equals(op) ) return OpOp2.LESS; |
| else if( ">=".equals(op) ) return OpOp2.GREATEREQUAL; |
| else if( ">".equals(op) ) return OpOp2.GREATER; |
| else if( "==".equals(op) ) return OpOp2.EQUAL; |
| else if( "!=".equals(op) ) return OpOp2.NOTEQUAL; |
| else if( "|".equals(op) ) return OpOp2.OR; |
| else if( "&".equals(op) ) return OpOp2.AND; |
| else if( "log".equals(op) ) return OpOp2.LOG; |
| else if( "^".equals(op) ) return OpOp2.POW; |
| |
| return null; |
| } |
| |
| public static ValueType getResultValueType(ValueType vt1, ValueType vt2) |
| { |
| if(vt1 == ValueType.STRING || vt2 == ValueType.STRING) |
| return ValueType.STRING; |
| else if(vt1 == ValueType.DOUBLE || vt2 == ValueType.DOUBLE) |
| return ValueType.DOUBLE; |
| else |
| return ValueType.INT; |
| } |
| |
| ///////////////////////////////////// |
| // methods for dynamic re-compilation |
| ///////////////////////////////////// |
| |
| /** |
| * Indicates if dynamic recompilation is required for this hop. |
| */ |
| public boolean requiresRecompile() |
| { |
| return _requiresRecompile; |
| } |
| |
| public void setRequiresRecompile() |
| { |
| _requiresRecompile = true; |
| } |
| |
| public void unsetRequiresRecompile() |
| { |
| _requiresRecompile = false; |
| } |
| |
| /** |
| * Update the output size information for this hop. |
| */ |
| public abstract void refreshSizeInformation(); |
| |
| /** |
| * Util function for refreshing scalar rows input parameter. |
| */ |
| protected void refreshRowsParameterInformation( Hop input ) |
| { |
| long size = computeSizeInformation(input); |
| |
| //always set the computed size not just if known (positive) in order to allow |
| //recompile with unknowns to reset sizes (otherwise potential for incorrect results) |
| setDim1( size ); |
| } |
| |
| |
| /** |
| * Util function for refreshing scalar cols input parameter. |
| */ |
| protected void refreshColsParameterInformation( Hop input ) |
| { |
| long size = computeSizeInformation(input); |
| |
| //always set the computed size not just if known (positive) in order to allow |
| //recompile with unknowns to reset sizes (otherwise potential for incorrect results) |
| setDim2( size ); |
| } |
| |
| /** |
| * |
| * @param input |
| * @return |
| */ |
| public long computeSizeInformation( Hop input ) |
| { |
| long ret = -1; |
| |
| try |
| { |
| long tmp = OptimizerUtils.rEvalSimpleLongExpression(input, new HashMap<Long,Long>()); |
| if( tmp!=Long.MAX_VALUE ) |
| ret = tmp; |
| } |
| catch(Exception ex) |
| { |
| LOG.error("Failed to compute size information.", ex); |
| ret = -1; |
| } |
| |
| return ret; |
| } |
| |
| /** |
| * |
| * @param input |
| * @param vars |
| */ |
| public void refreshRowsParameterInformation( Hop input, LocalVariableMap vars ) |
| { |
| long size = computeSizeInformation(input, vars); |
| |
| //always set the computed size not just if known (positive) in order to allow |
| //recompile with unknowns to reset sizes (otherwise potential for incorrect results) |
| setDim1( size ); |
| } |
| |
| /** |
| * |
| * @param input |
| * @param vars |
| */ |
| public void refreshColsParameterInformation( Hop input, LocalVariableMap vars ) |
| { |
| long size = computeSizeInformation(input, vars); |
| |
| //always set the computed size not just if known (positive) in order to allow |
| //recompile with unknowns to reset sizes (otherwise potential for incorrect results) |
| setDim2( size ); |
| } |
| |
| /** |
| * |
| * @param input |
| * @param vars |
| * @return |
| */ |
| public long computeSizeInformation( Hop input, LocalVariableMap vars ) |
| { |
| long ret = -1; |
| |
| try |
| { |
| long tmp = OptimizerUtils.rEvalSimpleLongExpression(input, new HashMap<Long,Long>(), vars); |
| if( tmp!=Long.MAX_VALUE ) |
| ret = tmp; |
| } |
| catch(Exception ex) |
| { |
| LOG.error("Failed to compute size information.", ex); |
| ret = -1; |
| } |
| |
| return ret; |
| } |
| |
| /** |
| * |
| * @param input |
| * @return |
| */ |
| public double computeBoundsInformation( Hop input ) |
| { |
| double ret = Double.MAX_VALUE; |
| |
| try |
| { |
| ret = OptimizerUtils.rEvalSimpleDoubleExpression(input, new HashMap<Long, Double>()); |
| } |
| catch(Exception ex) |
| { |
| LOG.error("Failed to compute bounds information.", ex); |
| ret = Double.MAX_VALUE; |
| } |
| |
| return ret; |
| } |
| |
| /** |
| * Computes bound information for sequence if possible, otherwise returns |
| * Double.MAX_VALUE |
| * |
| * @param input |
| * @param vars |
| * @return |
| */ |
| public double computeBoundsInformation( Hop input, LocalVariableMap vars ) |
| { |
| double ret = Double.MAX_VALUE; |
| |
| try |
| { |
| ret = OptimizerUtils.rEvalSimpleDoubleExpression(input, new HashMap<Long, Double>(), vars); |
| |
| } |
| catch(Exception ex) |
| { |
| LOG.error("Failed to compute bounds information.", ex); |
| ret = Double.MAX_VALUE; |
| } |
| |
| return ret; |
| } |
| |
| |
| /** |
| * Compute worst case estimate for size expression based on worst-case |
| * statistics of inputs. Limited set of supported operations in comparison |
| * to refresh rows/cols. |
| * |
| * @param input |
| * @param memo |
| */ |
| protected long computeDimParameterInformation( Hop input, MemoTable memo ) |
| { |
| long ret = -1; |
| |
| if( input instanceof UnaryOp ) |
| { |
| if( ((UnaryOp)input).getOp() == Hop.OpOp1.NROW ) |
| { |
| MatrixCharacteristics mc = memo.getAllInputStats(input.getInput().get(0)); |
| if( mc.getRows()>0 ) |
| ret = mc.getRows(); |
| } |
| else if ( ((UnaryOp)input).getOp() == Hop.OpOp1.NCOL ) |
| { |
| MatrixCharacteristics mc = memo.getAllInputStats(input.getInput().get(0)); |
| if( mc.getCols()>0 ) |
| ret = mc.getCols(); |
| } |
| } |
| else if ( input instanceof LiteralOp ) |
| { |
| ret = UtilFunctions.parseToLong(input.getName()); |
| } |
| else if ( input instanceof BinaryOp ) |
| { |
| long dim = rEvalSimpleBinaryLongExpression(input, new HashMap<Long, Long>(), memo); |
| if( dim != Long.MAX_VALUE ) //if known |
| ret = dim ; |
| } |
| |
| return ret; |
| } |
| |
| /** |
| * |
| * @param root |
| * @param valMemo |
| * @return |
| */ |
| protected long rEvalSimpleBinaryLongExpression( Hop root, HashMap<Long, Long> valMemo, MemoTable memo ) |
| { |
| //memoization (prevent redundant computation of common subexpr) |
| if( valMemo.containsKey(root.getHopID()) ) |
| return valMemo.get(root.getHopID()); |
| |
| long ret = Long.MAX_VALUE; |
| |
| if( root instanceof LiteralOp ) |
| { |
| long dim = UtilFunctions.parseToLong(root.getName()); |
| if( dim != -1 ) //if known |
| ret = dim; |
| } |
| else if( root instanceof UnaryOp ) |
| { |
| UnaryOp uroot = (UnaryOp) root; |
| long dim = -1; |
| if(uroot.getOp() == Hop.OpOp1.NROW) |
| { |
| MatrixCharacteristics mc = memo.getAllInputStats(uroot.getInput().get(0)); |
| dim = mc.getRows(); |
| } |
| else if( uroot.getOp() == Hop.OpOp1.NCOL ) |
| { |
| MatrixCharacteristics mc = memo.getAllInputStats(uroot.getInput().get(0)); |
| dim = mc.getCols(); |
| } |
| if( dim != -1 ) //if known |
| ret = dim; |
| } |
| else if( root instanceof BinaryOp ) |
| { |
| if( OptimizerUtils.ALLOW_WORSTCASE_SIZE_EXPRESSION_EVALUATION ) |
| { |
| BinaryOp broot = (BinaryOp) root; |
| long lret = rEvalSimpleBinaryLongExpression(broot.getInput().get(0), valMemo, memo); |
| long rret = rEvalSimpleBinaryLongExpression(broot.getInput().get(1), valMemo, memo); |
| //note: positive and negative values might be valid subexpressions |
| if( lret!=Long.MAX_VALUE && rret!=Long.MAX_VALUE ) //if known |
| { |
| switch( broot.getOp() ) |
| { |
| case PLUS: ret = lret + rret; break; |
| case MULT: ret = lret * rret; break; |
| case MIN: ret = Math.min(lret, rret); break; |
| case MAX: ret = Math.max(lret, rret); break; |
| default: ret = Long.MAX_VALUE; |
| } |
| } |
| //exploit min constraint to propagate |
| else if( broot.getOp()==OpOp2.MIN && (lret!=Double.MAX_VALUE || rret!=Double.MAX_VALUE) ) |
| { |
| ret = Math.min(lret, rret); |
| } |
| } |
| } |
| |
| valMemo.put(root.getHopID(), ret); |
| return ret; |
| } |
| |
| |
| /** |
| * |
| * @return |
| */ |
| public String constructBaseDir() |
| { |
| StringBuilder sb = new StringBuilder(); |
| sb.append( ConfigurationManager.getScratchSpace() ); |
| sb.append( Lop.FILE_SEPARATOR ); |
| sb.append( Lop.PROCESS_PREFIX ); |
| sb.append( DMLScript.getUUID() ); |
| sb.append( Lop.FILE_SEPARATOR ); |
| sb.append( Lop.FILE_SEPARATOR ); |
| sb.append( ProgramConverter.CP_ROOT_THREAD_ID ); |
| sb.append( Lop.FILE_SEPARATOR ); |
| |
| return sb.toString(); |
| } |
| |
| /** |
| * Clones the attributes of that and copies it over to this. |
| * |
| * @param that |
| * @throws HopsException |
| */ |
| protected void clone( Hop that, boolean withRefs ) |
| throws CloneNotSupportedException |
| { |
| if( withRefs ) |
| throw new CloneNotSupportedException( "Hops deep copy w/ lops/inputs/parents not supported." ); |
| |
| _ID = that._ID; |
| _name = that._name; |
| _dataType = that._dataType; |
| _valueType = that._valueType; |
| _visited = that._visited; |
| _dim1 = that._dim1; |
| _dim2 = that._dim2; |
| _rows_in_block = that._rows_in_block; |
| _cols_in_block = that._cols_in_block; |
| _nnz = that._nnz; |
| _updateType = that._updateType; |
| |
| //no copy of lops (regenerated) |
| _parent = new ArrayList<Hop>(); |
| _input = new ArrayList<Hop>(); |
| _lops = null; |
| |
| _etype = that._etype; |
| _etypeForced = that._etypeForced; |
| _outputMemEstimate = that._outputMemEstimate; |
| _memEstimate = that._memEstimate; |
| _processingMemEstimate = that._processingMemEstimate; |
| _requiresRecompile = that._requiresRecompile; |
| _requiresReblock = that._requiresReblock; |
| _requiresCheckpoint = that._requiresCheckpoint; |
| _outputEmptyBlocks = that._outputEmptyBlocks; |
| |
| _beginLine = that._beginLine; |
| _beginColumn = that._beginColumn; |
| _endLine = that._endLine; |
| _endColumn = that._endColumn; |
| } |
| |
| public abstract Object clone() throws CloneNotSupportedException; |
| |
| public abstract boolean compare( Hop that ); |
| |
| |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // store position information for Hops |
| /////////////////////////////////////////////////////////////////////////// |
| public int _beginLine, _beginColumn; |
| public int _endLine, _endColumn; |
| |
| public void setBeginLine(int passed) { _beginLine = passed; } |
| public void setBeginColumn(int passed) { _beginColumn = passed; } |
| public void setEndLine(int passed) { _endLine = passed; } |
| public void setEndColumn(int passed) { _endColumn = passed; } |
| |
| public void setAllPositions(int blp, int bcp, int elp, int ecp){ |
| _beginLine = blp; |
| _beginColumn = bcp; |
| _endLine = elp; |
| _endColumn = ecp; |
| } |
| |
| public int getBeginLine() { return _beginLine; } |
| public int getBeginColumn() { return _beginColumn; } |
| public int getEndLine() { return _endLine; } |
| public int getEndColumn() { return _endColumn; } |
| |
| public String printErrorLocation(){ |
| return "ERROR: line " + _beginLine + ", column " + _beginColumn + " -- "; |
| } |
| |
| public String printWarningLocation(){ |
| return "WARNING: line " + _beginLine + ", column " + _beginColumn + " -- "; |
| } |
| |
| /** |
| * Sets the linenumbers of this hop to a given lop. |
| * |
| * @param lop |
| */ |
| protected void setLineNumbers(Lop lop) |
| { |
| lop.setAllPositions(this.getBeginLine(), this.getBeginColumn(), this.getEndLine(), this.getEndColumn()); |
| } |
| |
| } // end class |