use of org.apache.sysml.parser.ParForStatementBlock in project incubator-systemml by apache.
the class ParForProgramBlock method getMinMemory.
private long getMinMemory(ExecutionContext ec) {
long ret = -1;
// if forced remote exec and single node
if (DMLScript.rtplatform == RUNTIME_PLATFORM.SINGLE_NODE && _execMode == PExecMode.REMOTE_MR && _optMode == POptMode.NONE) {
try {
ParForStatementBlock sb = (ParForStatementBlock) getStatementBlock();
OptTree tree = OptTreeConverter.createAbstractOptTree(-1, -1, sb, this, new HashSet<String>(), ec);
CostEstimator est = new CostEstimatorHops(OptTreeConverter.getAbstractPlanMapping());
double mem = est.getEstimate(TestMeasure.MEMORY_USAGE, tree.getRoot());
ret = (long) (mem * (1d / OptimizerUtils.MEM_UTIL_FACTOR));
} catch (Exception e) {
LOG.error("Failed to analyze minmum memory requirements.", e);
}
}
return ret;
}
use of org.apache.sysml.parser.ParForStatementBlock in project incubator-systemml by apache.
the class ParForProgramBlock method execute.
@Override
public void execute(ExecutionContext ec) {
ParForStatementBlock sb = (ParForStatementBlock) getStatementBlock();
// evaluate from, to, incr only once (assumption: known at for entry)
IntObject from = executePredicateInstructions(1, _fromInstructions, ec);
IntObject to = executePredicateInstructions(2, _toInstructions, ec);
IntObject incr = (_incrementInstructions == null || _incrementInstructions.isEmpty()) ? new IntObject((from.getLongValue() <= to.getLongValue()) ? 1 : -1) : executePredicateInstructions(3, _incrementInstructions, ec);
if (// would produce infinite loop
incr.getLongValue() == 0)
throw new DMLRuntimeException(this.printBlockErrorLocation() + "Expression for increment " + "of variable '" + _iterPredVar + "' must evaluate to a non-zero value.");
// early exit on num iterations = zero
_numIterations = computeNumIterations(from, to, incr);
if (_numIterations <= 0)
// avoid unnecessary optimization/initialization
return;
// /////
if (_optMode != POptMode.NONE) {
// set optimizer log level
OptimizationWrapper.setLogLevel(_optLogLevel);
// core optimize
OptimizationWrapper.optimize(_optMode, sb, this, ec, _monitor);
}
// /////
// DATA PARTITIONING of read-only parent variables of type (matrix,unpartitioned)
// /////
Timing time = _monitor ? new Timing(true) : null;
// partitioning on demand (note: for fused data partitioning and execute the optimizer set
// the data partitioner to NONE in order to prevent any side effects)
handleDataPartitioning(ec);
// repartitioning of variables for spark cpmm/zipmm in order prevent unnecessary shuffle
handleSparkRepartitioning(ec);
// eager rdd caching of variables for spark in order prevent read/write contention
handleSparkEagerCaching(ec);
if (_monitor)
StatisticMonitor.putPFStat(_ID, Stat.PARFOR_INIT_DATA_T, time.stop());
// initialize iter var to form value
IntObject iterVar = new IntObject(from.getLongValue());
// /////
// begin PARALLEL EXECUTION of (PAR)FOR body
// /////
LOG.trace("EXECUTE PARFOR ID = " + _ID + " with mode = " + _execMode + ", numThreads = " + _numThreads + ", taskpartitioner = " + _taskPartitioner);
if (_monitor) {
StatisticMonitor.putPFStat(_ID, Stat.PARFOR_NUMTHREADS, _numThreads);
StatisticMonitor.putPFStat(_ID, Stat.PARFOR_TASKSIZE, _taskSize);
StatisticMonitor.putPFStat(_ID, Stat.PARFOR_TASKPARTITIONER, _taskPartitioner.ordinal());
StatisticMonitor.putPFStat(_ID, Stat.PARFOR_DATAPARTITIONER, _dataPartitioner.ordinal());
StatisticMonitor.putPFStat(_ID, Stat.PARFOR_EXECMODE, _execMode.ordinal());
}
// preserve shared input/result variables of cleanup
ArrayList<String> varList = ec.getVarList();
boolean[] varState = ec.pinVariables(varList);
try {
switch(_execMode) {
case // create parworkers as local threads
LOCAL:
executeLocalParFor(ec, iterVar, from, to, incr);
break;
case // create parworkers as MR tasks (one job per parfor)
REMOTE_MR:
executeRemoteMRParFor(ec, iterVar, from, to, incr);
break;
case // create parworkers as MR tasks (one job per parfor)
REMOTE_MR_DP:
executeRemoteMRParForDP(ec, iterVar, from, to, incr);
break;
case // create parworkers as Spark tasks (one job per parfor)
REMOTE_SPARK:
executeRemoteSparkParFor(ec, iterVar, from, to, incr);
break;
case // create parworkers as Spark tasks (one job per parfor)
REMOTE_SPARK_DP:
executeRemoteSparkParForDP(ec, iterVar, from, to, incr);
break;
default:
throw new DMLRuntimeException("Undefined execution mode: '" + _execMode + "'.");
}
} catch (Exception ex) {
throw new DMLRuntimeException("PARFOR: Failed to execute loop in parallel.", ex);
}
// reset state of shared input/result variables
ec.unpinVariables(varList, varState);
// cleanup unpinned shared variables
cleanupSharedVariables(ec, varState);
// set iteration var to TO value (+ increment) for FOR equivalence
// consistent with for
iterVar = new IntObject(to.getLongValue());
ec.setVariable(_iterPredVar, iterVar);
// we can replace those variables, because partitioning only applied for read-only matrices
for (String var : _variablesDPOriginal.keySet()) {
// cleanup partitioned matrix (if not reused)
if (!_variablesDPReuse.keySet().contains(var))
VariableCPInstruction.processRemoveVariableInstruction(ec, var);
// reset to original matrix
MatrixObject mo = (MatrixObject) _variablesDPOriginal.get(var);
ec.setVariable(var, mo);
}
// print profiling report (only if top-level parfor because otherwise in parallel context)
if (_monitorReport)
LOG.info("\n" + StatisticMonitor.createReport());
// TODO reset of hop parallelism constraint (e.g., ba+*)
for (// release forced exectypes
String dpvar : // release forced exectypes
_variablesDPOriginal.keySet()) ProgramRecompiler.rFindAndRecompileIndexingHOP(sb, this, dpvar, ec, false);
// release forced exectypes for fused dp/exec
if (_execMode == PExecMode.REMOTE_MR_DP || _execMode == PExecMode.REMOTE_SPARK_DP)
ProgramRecompiler.rFindAndRecompileIndexingHOP(sb, this, _colocatedDPMatrix, ec, false);
// after release, deletes dp_varnames
resetOptimizerFlags();
// execute exit instructions (usually empty)
executeInstructions(_exitInstructions, ec);
}
use of org.apache.sysml.parser.ParForStatementBlock in project incubator-systemml by apache.
the class ParForProgramBlock method executeRemoteSparkParForDP.
private void executeRemoteSparkParForDP(ExecutionContext ec, IntObject itervar, IntObject from, IntObject to, IntObject incr) throws IOException {
Timing time = (_monitor ? new Timing(true) : null);
// Step 0) check and compile to CP (if forced remote parfor)
boolean flagForced = checkMRAndRecompileToCP(0);
// Step 1) prepare partitioned input matrix (needs to happen before serializing the program)
ParForStatementBlock sb = (ParForStatementBlock) getStatementBlock();
MatrixObject inputMatrix = ec.getMatrixObject(_colocatedDPMatrix);
PartitionFormat inputDPF = sb.determineDataPartitionFormat(_colocatedDPMatrix);
// mark matrix var as partitioned
inputMatrix.setPartitioned(inputDPF._dpf, inputDPF._N);
// Step 2) init parallel workers (serialize PBs)
// NOTES: each mapper changes filenames with regard to his ID as we submit a single
// job, cannot reuse serialized string, since variables are serialized as well.
ParForBody body = new ParForBody(_childBlocks, _resultVars, ec);
HashMap<String, byte[]> clsMap = new HashMap<>();
String program = ProgramConverter.serializeParForBody(body, clsMap);
if (_monitor)
StatisticMonitor.putPFStat(_ID, Stat.PARFOR_INIT_PARWRK_T, time.stop());
// Step 3) create tasks
TaskPartitioner partitioner = createTaskPartitioner(from, to, incr);
String resultFile = constructResultFileName();
long numIterations = partitioner.getNumIterations();
// partitioner.createTasks().size();
long numCreatedTasks = numIterations;
if (_monitor)
StatisticMonitor.putPFStat(_ID, Stat.PARFOR_INIT_TASKS_T, time.stop());
// write matrices to HDFS, except DP matrix which is the input to the RemoteDPParForSpark job
exportMatricesToHDFS(ec, _colocatedDPMatrix);
// Step 4) submit MR job (wait for finished work)
// TODO runtime support for binary cell partitioning
OutputInfo inputOI = OutputInfo.BinaryBlockOutputInfo;
RemoteParForJobReturn ret = RemoteDPParForSpark.runJob(_ID, _iterPredVar, _colocatedDPMatrix, program, clsMap, resultFile, inputMatrix, ec, inputDPF, inputOI, _tSparseCol, _enableCPCaching, _numThreads);
if (_monitor)
StatisticMonitor.putPFStat(_ID, Stat.PARFOR_WAIT_EXEC_T, time.stop());
// Step 5) collecting results from each parallel worker
int numExecutedTasks = ret.getNumExecutedTasks();
int numExecutedIterations = ret.getNumExecutedIterations();
// consolidate results into global symbol table
consolidateAndCheckResults(ec, numIterations, numCreatedTasks, numExecutedIterations, numExecutedTasks, ret.getVariables());
if (// see step 0
flagForced)
releaseForcedRecompile(0);
inputMatrix.unsetPartitioned();
if (_monitor) {
StatisticMonitor.putPFStat(_ID, Stat.PARFOR_WAIT_RESULTS_T, time.stop());
StatisticMonitor.putPFStat(_ID, Stat.PARFOR_NUMTASKS, numExecutedTasks);
StatisticMonitor.putPFStat(_ID, Stat.PARFOR_NUMITERS, numExecutedIterations);
}
}
use of org.apache.sysml.parser.ParForStatementBlock in project incubator-systemml by apache.
the class ParForProgramBlock method handleDataPartitioning.
private void handleDataPartitioning(ExecutionContext ec) {
PDataPartitioner dataPartitioner = _dataPartitioner;
if (dataPartitioner != PDataPartitioner.NONE) {
ParForStatementBlock sb = (ParForStatementBlock) getStatementBlock();
if (sb == null)
throw new DMLRuntimeException("ParFor statement block required for reasoning about data partitioning.");
for (String var : sb.getReadOnlyParentVars()) {
Data dat = ec.getVariable(var);
// partitioning but typically related branches are never executed)
if (dat != null && dat instanceof MatrixObject) {
// unpartitioned input
MatrixObject moVar = (MatrixObject) dat;
PartitionFormat dpf = sb.determineDataPartitionFormat(var);
LOG.trace("PARFOR ID = " + _ID + ", Partitioning read-only input variable " + var + " (format=" + dpf + ", mode=" + _dataPartitioner + ")");
if (dpf != PartitionFormat.NONE) {
if (dataPartitioner != PDataPartitioner.REMOTE_SPARK && dpf.isBlockwise()) {
LOG.warn("PARFOR ID = " + _ID + ", Switching data partitioner from " + dataPartitioner + " to " + PDataPartitioner.REMOTE_SPARK.name() + " for blockwise-n partitioning.");
dataPartitioner = PDataPartitioner.REMOTE_SPARK;
}
Timing ltime = new Timing(true);
// input data partitioning (reuse if possible)
Data dpdatNew = _variablesDPReuse.get(var);
if (// no reuse opportunity
dpdatNew == null) {
DataPartitioner dp = createDataPartitioner(dpf, dataPartitioner, ec);
// disable binary cell for sparse if consumed by MR jobs
if (!OptimizerRuleBased.allowsBinaryCellPartitions(moVar, dpf) || // TODO support for binarycell
OptimizerUtils.isSparkExecutionMode()) {
dp.disableBinaryCell();
}
MatrixObject moVarNew = dp.createPartitionedMatrixObject(moVar, constructDataPartitionsFileName());
dpdatNew = moVarNew;
// skip remaining partitioning logic if not partitioned (e.g., too small)
if (moVar == moVarNew)
// skip to next
continue;
}
ec.setVariable(var, dpdatNew);
// recompile parfor body program
ProgramRecompiler.rFindAndRecompileIndexingHOP(sb, this, var, ec, true);
// store original and partitioned matrix (for reuse if applicable)
_variablesDPOriginal.put(var, moVar);
if (ALLOW_REUSE_PARTITION_VARS && ProgramRecompiler.isApplicableForReuseVariable(sb.getDMLProg(), sb, var)) {
_variablesDPReuse.put(var, dpdatNew);
}
LOG.trace("Partitioning and recompilation done in " + ltime.stop() + "ms");
}
}
}
}
}
use of org.apache.sysml.parser.ParForStatementBlock in project incubator-systemml by apache.
the class Explain method getHopDAG.
private static StringBuilder getHopDAG(StatementBlock sb, StringBuilder nodes, ArrayList<Integer> lines, boolean withSubgraph) {
StringBuilder builder = new StringBuilder();
if (sb instanceof WhileStatementBlock) {
addSubGraphHeader(builder, withSubgraph);
WhileStatementBlock wsb = (WhileStatementBlock) sb;
String label = null;
if (!wsb.getUpdateInPlaceVars().isEmpty())
label = "WHILE (lines " + wsb.getBeginLine() + "-" + wsb.getEndLine() + ") in-place=" + wsb.getUpdateInPlaceVars().toString() + "";
else
label = "WHILE (lines " + wsb.getBeginLine() + "-" + wsb.getEndLine() + ")";
// TODO: Don't show predicate hops for now
// builder.append(explainHop(wsb.getPredicateHops()));
WhileStatement ws = (WhileStatement) sb.getStatement(0);
for (StatementBlock current : ws.getBody()) builder.append(getHopDAG(current, nodes, lines, withSubgraph));
addSubGraphFooter(builder, withSubgraph, label);
} else if (sb instanceof IfStatementBlock) {
addSubGraphHeader(builder, withSubgraph);
IfStatementBlock ifsb = (IfStatementBlock) sb;
String label = "IF (lines " + ifsb.getBeginLine() + "-" + ifsb.getEndLine() + ")";
// TODO: Don't show predicate hops for now
// builder.append(explainHop(ifsb.getPredicateHops(), level+1));
IfStatement ifs = (IfStatement) sb.getStatement(0);
for (StatementBlock current : ifs.getIfBody()) {
builder.append(getHopDAG(current, nodes, lines, withSubgraph));
addSubGraphFooter(builder, withSubgraph, label);
}
if (!ifs.getElseBody().isEmpty()) {
addSubGraphHeader(builder, withSubgraph);
label = "ELSE (lines " + ifsb.getBeginLine() + "-" + ifsb.getEndLine() + ")";
for (StatementBlock current : ifs.getElseBody()) builder.append(getHopDAG(current, nodes, lines, withSubgraph));
addSubGraphFooter(builder, withSubgraph, label);
}
} else if (sb instanceof ForStatementBlock) {
ForStatementBlock fsb = (ForStatementBlock) sb;
addSubGraphHeader(builder, withSubgraph);
String label = "";
if (sb instanceof ParForStatementBlock) {
if (!fsb.getUpdateInPlaceVars().isEmpty())
label = "PARFOR (lines " + fsb.getBeginLine() + "-" + fsb.getEndLine() + ") in-place=" + fsb.getUpdateInPlaceVars().toString() + "";
else
label = "PARFOR (lines " + fsb.getBeginLine() + "-" + fsb.getEndLine() + ")";
} else {
if (!fsb.getUpdateInPlaceVars().isEmpty())
label = "FOR (lines " + fsb.getBeginLine() + "-" + fsb.getEndLine() + ") in-place=" + fsb.getUpdateInPlaceVars().toString() + "";
else
label = "FOR (lines " + fsb.getBeginLine() + "-" + fsb.getEndLine() + ")";
}
// TODO: Don't show predicate hops for now
// if (fsb.getFromHops() != null)
// builder.append(explainHop(fsb.getFromHops(), level+1));
// if (fsb.getToHops() != null)
// builder.append(explainHop(fsb.getToHops(), level+1));
// if (fsb.getIncrementHops() != null)
// builder.append(explainHop(fsb.getIncrementHops(), level+1));
ForStatement fs = (ForStatement) sb.getStatement(0);
for (StatementBlock current : fs.getBody()) builder.append(getHopDAG(current, nodes, lines, withSubgraph));
addSubGraphFooter(builder, withSubgraph, label);
} else if (sb instanceof FunctionStatementBlock) {
FunctionStatement fsb = (FunctionStatement) sb.getStatement(0);
addSubGraphHeader(builder, withSubgraph);
String label = "Function (lines " + fsb.getBeginLine() + "-" + fsb.getEndLine() + ")";
for (StatementBlock current : fsb.getBody()) builder.append(getHopDAG(current, nodes, lines, withSubgraph));
addSubGraphFooter(builder, withSubgraph, label);
} else {
// For generic StatementBlock
if (sb.requiresRecompilation()) {
addSubGraphHeader(builder, withSubgraph);
}
ArrayList<Hop> hopsDAG = sb.getHops();
if (hopsDAG != null && !hopsDAG.isEmpty()) {
Hop.resetVisitStatus(hopsDAG);
for (Hop hop : hopsDAG) builder.append(getHopDAG(hop, nodes, lines, withSubgraph));
Hop.resetVisitStatus(hopsDAG);
}
if (sb.requiresRecompilation()) {
builder.append("style=filled;\n");
builder.append("color=lightgrey;\n");
String label = "(lines " + sb.getBeginLine() + "-" + sb.getEndLine() + ") [recompile=" + sb.requiresRecompilation() + "]";
addSubGraphFooter(builder, withSubgraph, label);
}
}
return builder;
}
Aggregations