/* * 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.runtime.controlprogram; import java.util.ArrayList; import java.util.HashMap; import org.apache.sysml.conf.ConfigurationManager; import org.apache.sysml.parser.DataIdentifier; import org.apache.sysml.parser.ExternalFunctionStatement; import org.apache.sysml.parser.Expression.ValueType; import org.apache.sysml.runtime.DMLRuntimeException; import org.apache.sysml.runtime.controlprogram.caching.MatrixObject; import org.apache.sysml.runtime.controlprogram.context.ExecutionContext; import org.apache.sysml.runtime.controlprogram.parfor.util.IDSequence; import org.apache.sysml.runtime.instructions.Instruction; import org.apache.sysml.runtime.matrix.MatrixCharacteristics; import org.apache.sysml.runtime.matrix.MatrixFormatMetaData; import org.apache.sysml.runtime.matrix.data.InputInfo; import org.apache.sysml.runtime.matrix.data.OutputInfo; import org.apache.sysml.udf.ExternalFunctionInvocationInstruction; import org.apache.sysml.udf.Matrix; /** * CP external function program block, that overcomes the need for * BlockToCell and CellToBlock MR jobs by changing the contract for an external function. * If execlocation="CP", the implementation of an external function must read and write * matrices as InputInfo.BinaryBlockInputInfo and OutputInfo.BinaryBlockOutputInfo. * * Furthermore, it extends ExternalFunctionProgramBlock with a base directory in order * to make it parallelizable, even in case of different JVMs. For this purpose every * external function must implement a <SET_BASE_DIR> method. * * */ public class ExternalFunctionProgramBlockCP extends ExternalFunctionProgramBlock { public static String DEFAULT_FILENAME = "ext_funct"; private static IDSequence _defaultSeq = new IDSequence(); /** * Constructor that also provides otherParams that are needed for external * functions. Remaining parameters will just be passed to constructor for * function program block. * * @param prog runtime program * @param inputParams list of input data identifiers * @param outputParams list of output data identifiers * @param otherParams map of other parameters * @param baseDir base directory * @throws DMLRuntimeException if DMLRuntimeException occurs */ public ExternalFunctionProgramBlockCP(Program prog, ArrayList<DataIdentifier> inputParams, ArrayList<DataIdentifier> outputParams, HashMap<String, String> otherParams, String baseDir) throws DMLRuntimeException { super(prog, inputParams, outputParams, baseDir); //w/o instruction generation // copy other params _otherParams = new HashMap<String, String>(); _otherParams.putAll(otherParams); // generate instructions (overwritten) createInstructions(); } /** * Method to be invoked to execute instructions for the external function * invocation */ @Override public void execute(ExecutionContext ec) throws DMLRuntimeException { _runID = _idSeq.getNextID(); ExternalFunctionInvocationInstruction inst = null; // execute package function for (int i=0; i < _inst.size(); i++) { try { inst = (ExternalFunctionInvocationInstruction)_inst.get(i); inst._namespace = _namespace; inst._functionName = _functionName; executeInstruction( ec, inst ); } catch (Exception e){ throw new DMLRuntimeException(this.printBlockErrorLocation() + "Error evaluating instruction " + i + " in external function programBlock. inst: " + inst.toString(), e); } } // check return values checkOutputParameters(ec.getVariables()); } /** * Executes the external function instruction. * */ @Override public void executeInstruction(ExecutionContext ec, ExternalFunctionInvocationInstruction inst) throws DMLRuntimeException { // After the udf framework rework, we moved the code of ExternalFunctionProgramBlockCP // to ExternalFunctionProgramBlock and hence hence both types of external functions can // share the same code path here. super.executeInstruction(ec, inst); } @Override protected void createInstructions() { _inst = new ArrayList<Instruction>(); // assemble information provided through keyvalue pairs String className = _otherParams.get(ExternalFunctionStatement.CLASS_NAME); String configFile = _otherParams.get(ExternalFunctionStatement.CONFIG_FILE); // class name cannot be null, however, configFile and execLocation can be null if (className == null) throw new RuntimeException(this.printBlockErrorLocation() + ExternalFunctionStatement.CLASS_NAME + " not provided!"); // assemble input and output param strings String inputParameterString = getParameterString(getInputParams()); String outputParameterString = getParameterString(getOutputParams()); // generate instruction ExternalFunctionInvocationInstruction einst = new ExternalFunctionInvocationInstruction( className, configFile, inputParameterString, outputParameterString); _inst.add(einst); } @Override protected void modifyInputMatrix(Matrix m, MatrixObject mobj) { //pass in-memory object to external function m.setMatrixObject( mobj ); } @Override protected MatrixObject createOutputMatrixObject(Matrix m) { MatrixObject ret = m.getMatrixObject(); if( ret == null ) //otherwise, pass in-memory matrix from extfunct back to invoking program { MatrixCharacteristics mc = new MatrixCharacteristics(m.getNumRows(),m.getNumCols(), ConfigurationManager.getBlocksize(), ConfigurationManager.getBlocksize()); MatrixFormatMetaData mfmd = new MatrixFormatMetaData(mc, OutputInfo.BinaryBlockOutputInfo, InputInfo.BinaryBlockInputInfo); ret = new MatrixObject(ValueType.DOUBLE, m.getFilePath(), mfmd); } //for allowing in-memory packagesupport matrices w/o filesnames if( ret.getFileName().equals( DEFAULT_FILENAME ) ) { ret.setFileName( createDefaultOutputFilePathAndName() ); } return ret; } public String createDefaultOutputFilePathAndName( ) { return _baseDir + DEFAULT_FILENAME + _defaultSeq.getNextID(); } public String printBlockErrorLocation(){ return "ERROR: Runtime error in external function program block (for CP) generated from external function statement block between lines " + _beginLine + " and " + _endLine + " -- "; } }