use of org.apache.sysml.runtime.controlprogram.LocalVariableMap in project incubator-systemml by apache.
the class ResourceOptimizer method getProgramCosts.
private static double getProgramCosts(ProgramBlock pb) {
double val = 0;
if (COST_INDIVIDUAL_BLOCKS) {
LocalVariableMap vars = new LocalVariableMap();
collectReadVariables(pb.getStatementBlock().getHops(), vars);
ExecutionContext ec = ExecutionContextFactory.createContext(false, null);
ec.setVariables(vars);
val = CostEstimationWrapper.getTimeEstimate(pb, ec, false);
} else {
// we need to cost the entire program in order to take in-memory status into account
ExecutionContext ec = ExecutionContextFactory.createContext();
val = CostEstimationWrapper.getTimeEstimate(pb.getProgram(), ec);
}
_cntCostPB++;
return val;
}
use of org.apache.sysml.runtime.controlprogram.LocalVariableMap in project incubator-systemml by apache.
the class OptimizerRuleBased method rewriteSetInPlaceResultIndexing.
///////
//REWRITE set in-place result indexing
///
protected void rewriteSetInPlaceResultIndexing(OptNode pn, double M, LocalVariableMap vars, HashSet<String> inPlaceResultVars, ExecutionContext ec) throws DMLRuntimeException {
//assertions (warnings of corrupt optimizer decisions)
if (pn.getNodeType() != NodeType.PARFOR)
LOG.warn(getOptMode() + " OPT: Set in-place result update is only applicable for a ParFor node.");
boolean apply = false;
ParForProgramBlock pfpb = (ParForProgramBlock) OptTreeConverter.getAbstractPlanMapping().getMappedProg(pn.getID())[1];
//note currently we decide for all result vars jointly, i.e.,
//only if all fit pinned in remaining budget, we apply this rewrite.
ArrayList<String> retVars = pfpb.getResultVariables();
//compute total sum of pinned result variable memory
double sum = computeTotalSizeResultVariables(retVars, vars, pfpb.getDegreeOfParallelism());
//NOTE: currently this rule is too conservative (the result variable is assumed to be dense and
//most importantly counted twice if this is part of the maximum operation)
HashMap<String, ArrayList<UIPCandidateHop>> uipCandHopHM = new HashMap<String, ArrayList<UIPCandidateHop>>();
double totalMem = Math.max((M + sum), rComputeSumMemoryIntermediates(pn, new HashSet<String>(), uipCandHopHM));
//optimization decision
if (//basic correctness constraint
rHasOnlyInPlaceSafeLeftIndexing(pn, retVars)) {
//result update in-place for MR/Spark (w/ remote memory constraint)
if ((pfpb.getExecMode() == PExecMode.REMOTE_MR_DP || pfpb.getExecMode() == PExecMode.REMOTE_MR || pfpb.getExecMode() == PExecMode.REMOTE_SPARK_DP || pfpb.getExecMode() == PExecMode.REMOTE_SPARK) && totalMem < _rm) {
apply = true;
} else //result update in-place for CP (w/ local memory constraint)
if (pfpb.getExecMode() == PExecMode.LOCAL && totalMem * pfpb.getDegreeOfParallelism() < _lm && //no forced mr/spark execution
pn.isCPOnly()) {
apply = true;
}
}
if (APPLY_REWRITE_UPDATE_INPLACE_INTERMEDIATE && LOG.isDebugEnabled())
listUIPRes.remove();
//modify result variable meta data, if rewrite applied
if (apply) {
//will be serialized and transfered via symbol table
for (String var : retVars) {
Data dat = vars.get(var);
if (dat instanceof MatrixObject)
((MatrixObject) dat).setUpdateType(UpdateType.INPLACE_PINNED);
}
inPlaceResultVars.addAll(retVars);
if (APPLY_REWRITE_UPDATE_INPLACE_INTERMEDIATE) {
isUpdateInPlaceApplicable(pn, uipCandHopHM);
boolean bAnyUIPApplicable = false;
for (Entry<String, ArrayList<UIPCandidateHop>> entry : uipCandHopHM.entrySet()) {
ArrayList<UIPCandidateHop> uipCandHopList = entry.getValue();
if (uipCandHopList != null) {
for (UIPCandidateHop uipCandHop : uipCandHopList) if (uipCandHop.isIntermediate() && uipCandHop.isLoopApplicable() && uipCandHop.isUpdateInPlace()) {
uipCandHop.getHop().setUpdateType(UpdateType.INPLACE_PINNED);
bAnyUIPApplicable = true;
if (LOG.isDebugEnabled())
listUIPRes.get().add(uipCandHop.getHop().getName());
}
}
}
if (bAnyUIPApplicable)
try {
//Recompile this block recursively if there is any update in place applicable.
LocalVariableMap localVaraibleMap = (LocalVariableMap) ec.getVariables().clone();
Recompiler.recompileProgramBlockHierarchy(pfpb.getChildBlocks(), localVaraibleMap, 0L, true);
} catch (Exception ex) {
throw new DMLRuntimeException(ex);
}
}
}
if (APPLY_REWRITE_UPDATE_INPLACE_INTERMEDIATE && LOG.isTraceEnabled()) {
LOG.trace("UpdateInPlace = " + apply + " for lines between " + pn.getBeginLine() + " and " + pn.getEndLine() + " for " + uipCandHopHM.size() + " intermediate matrix objects:" + uipCandHopHM.keySet().toString());
for (Entry<String, ArrayList<UIPCandidateHop>> entry : uipCandHopHM.entrySet()) {
ArrayList<UIPCandidateHop> uipCandHopList = entry.getValue();
if (uipCandHopList != null) {
for (UIPCandidateHop uipCandHop : uipCandHopList) {
if (uipCandHop.getHop() != null) {
LOG.trace("Matrix Object: Name: " + uipCandHop.getHop().getName() + "<" + uipCandHop.getHop().getBeginLine() + "," + uipCandHop.getHop().getEndLine() + ">, InLoop:" + uipCandHop.isLoopApplicable() + ", UIPApplicable:" + uipCandHop.isUpdateInPlace() + ", HopUIPApplicable:" + uipCandHop.getHop().getUpdateType());
LOG.trace("Explain Candidate HOP after recompile");
LOG.trace(Explain.explain(uipCandHop.getHop()));
} else {
LOG.trace("Matrix Object: Name: " + uipCandHop.getLixHop().getName() + "<" + uipCandHop.getLixHop().getBeginLine() + "," + uipCandHop.getLixHop().getEndLine() + ">, InLoop:" + uipCandHop.isLoopApplicable() + ", Not an Intermediate matrix object");
}
}
}
}
}
LOG.debug(getOptMode() + " OPT: rewrite 'set in-place result indexing' - result=" + apply + " (" + ProgramConverter.serializeStringCollection(inPlaceResultVars) + ", M=" + toMB(totalMem) + ")");
}
use of org.apache.sysml.runtime.controlprogram.LocalVariableMap in project incubator-systemml by apache.
the class InterProceduralAnalysis method propagateStatisticsIntoFunctions.
/**
* Propagate statistics from the calling program into a function
* block.
*
* @param prog The DML program.
* @param hop HOP to propagate statistics into.
* @param fcand Function candidates.
* @param callVars Calling program's map of variables eligible for
* propagation.
* @param fcandSafeNNZ Function candidate safe non-zeros.
* @param unaryFcands Unary function candidates.
* @param fnStack Function stack to determine current scope.
* @throws HopsException If a HopsException occurs.
* @throws ParseException If a ParseException occurs.
*/
private void propagateStatisticsIntoFunctions(DMLProgram prog, Hop hop, Map<String, Integer> fcand, LocalVariableMap callVars, Map<String, Set<Long>> fcandSafeNNZ, Set<String> unaryFcands, Set<String> fnStack) throws HopsException, ParseException {
if (hop.isVisited())
return;
for (Hop c : hop.getInput()) propagateStatisticsIntoFunctions(prog, c, fcand, callVars, fcandSafeNNZ, unaryFcands, fnStack);
if (hop instanceof FunctionOp) {
//maintain counters and investigate functions if not seen so far
FunctionOp fop = (FunctionOp) hop;
String fkey = DMLProgram.constructFunctionKey(fop.getFunctionNamespace(), fop.getFunctionName());
if (fop.getFunctionType() == FunctionType.DML) {
FunctionStatementBlock fsb = prog.getFunctionStatementBlock(fop.getFunctionNamespace(), fop.getFunctionName());
FunctionStatement fstmt = (FunctionStatement) fsb.getStatement(0);
if (fcand.containsKey(fkey) && //prevent recursion
!fnStack.contains(fkey)) {
//maintain function call stack
fnStack.add(fkey);
//create mapping and populate symbol table for refresh
LocalVariableMap tmpVars = new LocalVariableMap();
populateLocalVariableMapForFunctionCall(fstmt, fop, callVars, tmpVars, fcandSafeNNZ.get(fkey), fcand.get(fkey));
//recursively propagate statistics
propagateStatisticsAcrossBlock(fsb, fcand, tmpVars, fcandSafeNNZ, unaryFcands, fnStack);
//extract vars from symbol table, re-map and refresh main program
extractFunctionCallReturnStatistics(fstmt, fop, tmpVars, callVars, true);
//maintain function call stack
fnStack.remove(fkey);
} else if (unaryFcands.contains(fkey)) {
extractFunctionCallEquivalentReturnStatistics(fstmt, fop, callVars);
} else {
extractFunctionCallUnknownReturnStatistics(fstmt, fop, callVars);
}
} else if (fop.getFunctionType() == FunctionType.EXTERNAL_FILE || fop.getFunctionType() == FunctionType.EXTERNAL_MEM) {
//infer output size for known external functions
FunctionStatementBlock fsb = prog.getFunctionStatementBlock(fop.getFunctionNamespace(), fop.getFunctionName());
ExternalFunctionStatement fstmt = (ExternalFunctionStatement) fsb.getStatement(0);
if (PROPAGATE_KNOWN_UDF_STATISTICS)
extractExternalFunctionCallReturnStatistics(fstmt, fop, callVars);
else
extractFunctionCallUnknownReturnStatistics(fstmt, fop, callVars);
}
}
hop.setVisited();
}
use of org.apache.sysml.runtime.controlprogram.LocalVariableMap in project incubator-systemml by apache.
the class InterProceduralAnalysis method analyzeProgram.
/**
* Public interface to perform IPA over a given DML program.
*
* @param dmlp the dml program
* @throws HopsException if HopsException occurs
* @throws ParseException if ParseException occurs
* @throws LanguageException if LanguageException occurs
*/
public void analyzeProgram(DMLProgram dmlp) throws HopsException, ParseException, LanguageException {
FunctionCallGraph fgraph = new FunctionCallGraph(dmlp);
//step 1: get candidates for statistics propagation into functions (if required)
Map<String, Integer> fcandCounts = new HashMap<String, Integer>();
Map<String, FunctionOp> fcandHops = new HashMap<String, FunctionOp>();
Map<String, Set<Long>> fcandSafeNNZ = new HashMap<String, Set<Long>>();
if (!dmlp.getFunctionStatementBlocks().isEmpty()) {
for (//get candidates (over entire program)
StatementBlock sb : //get candidates (over entire program)
dmlp.getStatementBlocks()) getFunctionCandidatesForStatisticPropagation(sb, fcandCounts, fcandHops);
pruneFunctionCandidatesForStatisticPropagation(fcandCounts, fcandHops);
determineFunctionCandidatesNNZPropagation(fcandHops, fcandSafeNNZ);
DMLTranslator.resetHopsDAGVisitStatus(dmlp);
}
//step 2: get unary dimension-preserving non-candidate functions
Collection<String> unaryFcandTmp = fgraph.getReachableFunctions(fcandCounts.keySet());
HashSet<String> unaryFcands = new HashSet<String>();
if (!unaryFcandTmp.isEmpty() && UNARY_DIMS_PRESERVING_FUNS) {
for (String tmp : unaryFcandTmp) if (isUnarySizePreservingFunction(dmlp.getFunctionStatementBlock(tmp)))
unaryFcands.add(tmp);
}
//step 3: propagate statistics and scalars into functions and across DAGs
if (!fcandCounts.isEmpty() || INTRA_PROCEDURAL_ANALYSIS) {
//(callVars used to chain outputs/inputs of multiple functions calls)
LocalVariableMap callVars = new LocalVariableMap();
for (//propagate stats into candidates
StatementBlock sb : //propagate stats into candidates
dmlp.getStatementBlocks()) propagateStatisticsAcrossBlock(sb, fcandCounts, callVars, fcandSafeNNZ, unaryFcands, new HashSet<String>());
}
//step 4: remove unused functions (e.g., inlined or never called)
if (REMOVE_UNUSED_FUNCTIONS) {
removeUnusedFunctions(dmlp, fgraph);
}
//step 5: flag functions with loops for 'recompile-on-entry'
if (FLAG_FUNCTION_RECOMPILE_ONCE) {
flagFunctionsForRecompileOnce(dmlp, fgraph);
}
//step 6: set global data flow properties
if (REMOVE_UNNECESSARY_CHECKPOINTS && OptimizerUtils.isSparkExecutionMode()) {
//remove unnecessary checkpoint before update
removeCheckpointBeforeUpdate(dmlp);
//move necessary checkpoint after update
moveCheckpointAfterUpdate(dmlp);
//remove unnecessary checkpoint read-{write|uagg}
removeCheckpointReadWrite(dmlp);
}
//step 7: remove constant binary ops
if (REMOVE_CONSTANT_BINARY_OPS) {
removeConstantBinaryOps(dmlp);
}
}
use of org.apache.sysml.runtime.controlprogram.LocalVariableMap in project incubator-systemml by apache.
the class GDFEnumOptimizer method costRuntimePlan.
private static double costRuntimePlan(Plan p) throws DMLRuntimeException {
Program prog = p.getNode().getProgram();
if (prog == null)
throw new DMLRuntimeException("Program not available for runtime plan costing.");
//put data flow configuration into program
rSetRuntimePlanConfig(p, new HashMap<Long, Plan>());
double costs = -1;
if (COST_FULL_PROGRAMS || (p.getNode().getHop() == null || p.getNode().getProgramBlock() == null)) {
//recompile entire runtime program
Recompiler.recompileProgramBlockHierarchy(prog.getProgramBlocks(), new LocalVariableMap(), 0, false);
_compiledPlans++;
//cost entire runtime program
ExecutionContext ec = ExecutionContextFactory.createContext(prog);
costs = CostEstimationWrapper.getTimeEstimate(prog, ec);
} else {
Hop currentHop = p.getNode().getHop();
ProgramBlock pb = p.getNode().getProgramBlock();
try {
//keep the old dag roots
ArrayList<Hop> oldRoots = pb.getStatementBlock().get_hops();
Hop tmpHop = null;
if (!(currentHop instanceof DataOp && ((DataOp) currentHop).isWrite())) {
ArrayList<Hop> newRoots = new ArrayList<Hop>();
tmpHop = new DataOp("_tmp", currentHop.getDataType(), currentHop.getValueType(), currentHop, DataOpTypes.TRANSIENTWRITE, "tmp");
//ensure recursive visitstatus reset on recompile
tmpHop.setVisited();
newRoots.add(tmpHop);
pb.getStatementBlock().set_hops(newRoots);
}
//recompile modified runtime program
Recompiler.recompileProgramBlockHierarchy(prog.getProgramBlocks(), new LocalVariableMap(), 0, false);
_compiledPlans++;
//cost partial runtime program up to current hop
ExecutionContext ec = ExecutionContextFactory.createContext(prog);
costs = CostEstimationWrapper.getTimeEstimate(prog, ec);
//restore original hop dag
if (tmpHop != null)
HopRewriteUtils.removeChildReference(tmpHop, currentHop);
pb.getStatementBlock().set_hops(oldRoots);
} catch (HopsException ex) {
throw new DMLRuntimeException(ex);
}
}
//release forced data flow configuration from program
rResetRuntimePlanConfig(p, new HashMap<Long, Plan>());
_costedPlans++;
return costs;
}
Aggregations