use of org.apache.sysml.runtime.controlprogram.ParForProgramBlock in project incubator-systemml by apache.
the class OptimizerRuleBased method rValidateUIPConsumerList.
/*
* This will validate candidate's consumer list.
*
* @param pn: OpNode of parfor loop
* @param uipCandHopHM: Hashmap of UIPCandidateHop with name as a key.
* @throws DMLRuntimeException
*/
private void rValidateUIPConsumerList(OptNode pn, HashMap<String, ArrayList<UIPCandidateHop>> uipCandHopHM) throws DMLRuntimeException {
if (!pn.isLeaf()) {
if (pn.getNodeType() == OptNode.NodeType.FUNCCALL) {
Hop hop = (Hop) OptTreeConverter.getAbstractPlanMapping().getMappedHop(pn.getID());
rValidateUIPConsumerList(hop.getInput(), uipCandHopHM);
return;
}
ProgramBlock pb = (ProgramBlock) OptTreeConverter.getAbstractPlanMapping().getMappedProg(pn.getID())[1];
VariableSet varRead = pb.getStatementBlock().variablesRead();
boolean bUIPCandHopRead = false;
for (Entry<String, ArrayList<UIPCandidateHop>> entry : uipCandHopHM.entrySet()) {
ArrayList<UIPCandidateHop> uipCandHopList = entry.getValue();
if (uipCandHopList != null) {
for (UIPCandidateHop uipCandHop : uipCandHopList) {
ArrayList<Hop> consumerHops = uipCandHop.getConsumerHops();
if (consumerHops != null) {
// remove candidate from the list.
for (Hop consumerHop : consumerHops) {
if (varRead.containsVariable(consumerHop.getName())) {
bUIPCandHopRead = true;
break;
}
}
}
}
}
}
// As none of the UIP candidates updated in this DAG, no need for further processing within this DAG
if (!bUIPCandHopRead)
return;
for (OptNode optNode : pn.getChilds()) rValidateUIPConsumerList(optNode, uipCandHopHM);
} else {
OptTreePlanMappingAbstract map = OptTreeConverter.getAbstractPlanMapping();
long ppid = map.getMappedParentID(map.getMappedParentID(pn.getID()));
Object[] o = map.getMappedProg(ppid);
ProgramBlock pb = (ProgramBlock) o[1];
if (pb instanceof IfProgramBlock || pb instanceof WhileProgramBlock || //TODO
(pb instanceof ForProgramBlock && !(pb instanceof ParForProgramBlock)))
rValidateUIPConsumerList(pb, uipCandHopHM);
long pid = map.getMappedParentID(pn.getID());
o = map.getMappedProg(pid);
pb = (ProgramBlock) o[1];
Hop hop = map.getMappedHop(pn.getID());
rValidateUIPConsumerList(hop, uipCandHopHM, pb.getStatementBlock().variablesRead());
}
}
use of org.apache.sysml.runtime.controlprogram.ParForProgramBlock in project incubator-systemml by apache.
the class OptimizerRuleBased method rGetUIPConsumerList.
/*
* This will get consumer list for candidate LeftIndexingOp.
*
* @param pn: OpNode of parfor loop
* @param uipCandHopHM: Hashmap of UIPCandidateHop with name as a key.
* @throws DMLRuntimeException
*/
private void rGetUIPConsumerList(OptNode pn, HashMap<String, ArrayList<UIPCandidateHop>> uipCandHopHM) throws DMLRuntimeException {
if (!pn.isLeaf()) {
if (pn.getNodeType() == OptNode.NodeType.FUNCCALL)
return;
ProgramBlock pb = (ProgramBlock) OptTreeConverter.getAbstractPlanMapping().getMappedProg(pn.getID())[1];
VariableSet varRead = pb.getStatementBlock().variablesRead();
boolean bUIPCandHopRead = false;
for (Entry<String, ArrayList<UIPCandidateHop>> entry : uipCandHopHM.entrySet()) {
String uipCandHopID = entry.getKey();
if (varRead.containsVariable(uipCandHopID)) {
bUIPCandHopRead = true;
break;
}
}
// As none of the UIP candidates updated in this DAG, no need for further processing within this DAG
if (!bUIPCandHopRead)
return;
for (OptNode optNode : pn.getChilds()) rGetUIPConsumerList(optNode, uipCandHopHM);
} else {
OptTreePlanMappingAbstract map = OptTreeConverter.getAbstractPlanMapping();
long ppid = map.getMappedParentID(map.getMappedParentID(pn.getID()));
Object[] o = map.getMappedProg(ppid);
ProgramBlock pb = (ProgramBlock) o[1];
Hop hop = (Hop) OptTreeConverter.getAbstractPlanMapping().getMappedHop(pn.getID());
rGetUIPConsumerList(hop, uipCandHopHM);
if (pb instanceof IfProgramBlock || pb instanceof WhileProgramBlock || //TODO
(pb instanceof ForProgramBlock && !(pb instanceof ParForProgramBlock)))
rGetUIPConsumerList(pb, uipCandHopHM);
}
}
use of org.apache.sysml.runtime.controlprogram.ParForProgramBlock 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.ParForProgramBlock in project incubator-systemml by apache.
the class DMLProgram method addCleanupInstruction.
/**
* Adds the generated cleanup RMVAR instruction to the given program block.
* In case of generic (last-level) programblocks it is added to the end of
* the list of instructions, while for complex program blocks it is added to
* the end of the list of exit instructions.
*
* @param pb program block
* @param inst instruction
* @throws DMLRuntimeException if DMLRuntimeException occurs
*/
private void addCleanupInstruction(ProgramBlock pb, Instruction inst) throws DMLRuntimeException {
if (pb instanceof WhileProgramBlock) {
WhileProgramBlock wpb = (WhileProgramBlock) pb;
ArrayList<ProgramBlock> childs = wpb.getChildBlocks();
if (//generic last level pb
!childs.get(childs.size() - 1).getInstructions().isEmpty())
childs.get(childs.size() - 1).addInstruction(inst);
else {
ProgramBlock pbNew = new ProgramBlock(pb.getProgram());
pbNew.addInstruction(inst);
childs.add(pbNew);
}
} else if (//includes ParFORProgramBlock
pb instanceof ForProgramBlock) {
ForProgramBlock wpb = (ForProgramBlock) pb;
ArrayList<ProgramBlock> childs = wpb.getChildBlocks();
if (//generic last level pb
!childs.get(childs.size() - 1).getInstructions().isEmpty())
childs.get(childs.size() - 1).addInstruction(inst);
else {
ProgramBlock pbNew = new ProgramBlock(pb.getProgram());
pbNew.addInstruction(inst);
childs.add(pbNew);
}
} else if (pb instanceof IfProgramBlock)
((IfProgramBlock) pb).addExitInstruction(inst);
else if (//includes ExternalFunctionProgramBlock and ExternalFunctionProgramBlockCP)
pb instanceof FunctionProgramBlock)
//do nothing
;
else {
//add inst at end of pb
pb.addInstruction(inst);
}
}
use of org.apache.sysml.runtime.controlprogram.ParForProgramBlock in project incubator-systemml by apache.
the class DMLTranslator method createRuntimeProgramBlock.
public ProgramBlock createRuntimeProgramBlock(Program prog, StatementBlock sb, DMLConfig config) {
Dag<Lop> dag = null;
Dag<Lop> pred_dag = null;
ArrayList<Instruction> instruct;
ArrayList<Instruction> pred_instruct = null;
ProgramBlock retPB = null;
// process While Statement - add runtime program blocks to program
if (sb instanceof WhileStatementBlock) {
// create DAG for loop predicates
pred_dag = new Dag<>();
((WhileStatementBlock) sb).get_predicateLops().addToDag(pred_dag);
// create instructions for loop predicates
pred_instruct = new ArrayList<>();
ArrayList<Instruction> pInst = pred_dag.getJobs(null, config);
for (Instruction i : pInst) {
pred_instruct.add(i);
}
// create while program block
WhileProgramBlock rtpb = new WhileProgramBlock(prog, pred_instruct);
// // process the body of the while statement block ////
WhileStatementBlock wsb = (WhileStatementBlock) sb;
WhileStatement wstmt = (WhileStatement) wsb.getStatement(0);
for (StatementBlock sblock : wstmt.getBody()) {
// process the body
ProgramBlock childBlock = createRuntimeProgramBlock(prog, sblock, config);
rtpb.addProgramBlock(childBlock);
}
retPB = rtpb;
// add statement block
retPB.setStatementBlock(sb);
// add location information
retPB.setParseInfo(sb);
} else // process If Statement - add runtime program blocks to program
if (sb instanceof IfStatementBlock) {
// create DAG for loop predicates
pred_dag = new Dag<>();
((IfStatementBlock) sb).get_predicateLops().addToDag(pred_dag);
// create instructions for loop predicates
pred_instruct = new ArrayList<>();
ArrayList<Instruction> pInst = pred_dag.getJobs(null, config);
for (Instruction i : pInst) {
pred_instruct.add(i);
}
// create if program block
IfProgramBlock rtpb = new IfProgramBlock(prog, pred_instruct);
// process the body of the if statement block
IfStatementBlock isb = (IfStatementBlock) sb;
IfStatement istmt = (IfStatement) isb.getStatement(0);
// process the if body
for (StatementBlock sblock : istmt.getIfBody()) {
ProgramBlock childBlock = createRuntimeProgramBlock(prog, sblock, config);
rtpb.addProgramBlockIfBody(childBlock);
}
// process the else body
for (StatementBlock sblock : istmt.getElseBody()) {
ProgramBlock childBlock = createRuntimeProgramBlock(prog, sblock, config);
rtpb.addProgramBlockElseBody(childBlock);
}
retPB = rtpb;
// post processing for generating missing instructions
// retPB = verifyAndCorrectProgramBlock(sb.liveIn(), sb.liveOut(), sb._kill, retPB);
// add statement block
retPB.setStatementBlock(sb);
// add location information
retPB.setParseInfo(sb);
} else // NOTE: applies to ForStatementBlock and ParForStatementBlock
if (sb instanceof ForStatementBlock) {
ForStatementBlock fsb = (ForStatementBlock) sb;
// create DAGs for loop predicates
Dag<Lop> fromDag = new Dag<>();
Dag<Lop> toDag = new Dag<>();
Dag<Lop> incrementDag = new Dag<>();
if (fsb.getFromHops() != null)
fsb.getFromLops().addToDag(fromDag);
if (fsb.getToHops() != null)
fsb.getToLops().addToDag(toDag);
if (fsb.getIncrementHops() != null)
fsb.getIncrementLops().addToDag(incrementDag);
// create instructions for loop predicates
ArrayList<Instruction> fromInstructions = fromDag.getJobs(null, config);
ArrayList<Instruction> toInstructions = toDag.getJobs(null, config);
ArrayList<Instruction> incrementInstructions = incrementDag.getJobs(null, config);
// create for program block
ForProgramBlock rtpb = null;
IterablePredicate iterPred = fsb.getIterPredicate();
if (sb instanceof ParForStatementBlock && ConfigurationManager.isParallelParFor()) {
rtpb = new ParForProgramBlock(prog, iterPred.getIterVar().getName(), iterPred.getParForParams(), ((ParForStatementBlock) sb).getResultVariables());
ParForProgramBlock pfrtpb = (ParForProgramBlock) rtpb;
// used for optimization and creating unscoped variables
pfrtpb.setStatementBlock((ParForStatementBlock) sb);
} else {
// ForStatementBlock
rtpb = new ForProgramBlock(prog, iterPred.getIterVar().getName());
}
rtpb.setFromInstructions(fromInstructions);
rtpb.setToInstructions(toInstructions);
rtpb.setIncrementInstructions(incrementInstructions);
// process the body of the for statement block
ForStatement fs = (ForStatement) fsb.getStatement(0);
for (StatementBlock sblock : fs.getBody()) {
ProgramBlock childBlock = createRuntimeProgramBlock(prog, sblock, config);
rtpb.addProgramBlock(childBlock);
}
retPB = rtpb;
// add statement block
retPB.setStatementBlock(sb);
// add location information
retPB.setParseInfo(sb);
} else // process function statement block - add runtime program blocks to program
if (sb instanceof FunctionStatementBlock) {
FunctionStatementBlock fsb = (FunctionStatementBlock) sb;
FunctionStatement fstmt = (FunctionStatement) fsb.getStatement(0);
FunctionProgramBlock rtpb = null;
if (fstmt instanceof ExternalFunctionStatement) {
// create external function program block
String execType = ((ExternalFunctionStatement) fstmt).getOtherParams().get(ExternalFunctionStatement.EXEC_TYPE);
boolean isCP = (execType.equals(ExternalFunctionStatement.IN_MEMORY)) ? true : false;
StringBuilder buff = new StringBuilder();
buff.append(config.getTextValue(DMLConfig.SCRATCH_SPACE));
buff.append(Lop.FILE_SEPARATOR);
buff.append(Lop.PROCESS_PREFIX);
buff.append(DMLScript.getUUID());
buff.append(Lop.FILE_SEPARATOR);
buff.append(ProgramConverter.CP_ROOT_THREAD_ID);
buff.append(Lop.FILE_SEPARATOR);
buff.append("PackageSupport");
buff.append(Lop.FILE_SEPARATOR);
String basedir = buff.toString();
if (isCP) {
rtpb = new ExternalFunctionProgramBlockCP(prog, fstmt.getInputParams(), fstmt.getOutputParams(), ((ExternalFunctionStatement) fstmt).getOtherParams(), basedir);
} else {
rtpb = new ExternalFunctionProgramBlock(prog, fstmt.getInputParams(), fstmt.getOutputParams(), ((ExternalFunctionStatement) fstmt).getOtherParams(), basedir);
}
if (!fstmt.getBody().isEmpty()) {
LOG.error(fstmt.printErrorLocation() + "ExternalFunctionStatementBlock should have no statement blocks in body");
throw new LopsException(fstmt.printErrorLocation() + "ExternalFunctionStatementBlock should have no statement blocks in body");
}
} else {
// create function program block
rtpb = new FunctionProgramBlock(prog, fstmt.getInputParams(), fstmt.getOutputParams());
// process the function statement body
for (StatementBlock sblock : fstmt.getBody()) {
// process the body
ProgramBlock childBlock = createRuntimeProgramBlock(prog, sblock, config);
rtpb.addProgramBlock(childBlock);
}
}
// check there are actually Lops in to process (loop stmt body will not have any)
if (fsb.getLops() != null && !fsb.getLops().isEmpty()) {
LOG.error(fsb.printBlockErrorLocation() + "FunctionStatementBlock should have no Lops");
throw new LopsException(fsb.printBlockErrorLocation() + "FunctionStatementBlock should have no Lops");
}
retPB = rtpb;
// add location information
retPB.setParseInfo(sb);
} else {
// handle general case
ProgramBlock rtpb = new ProgramBlock(prog);
// DAGs for Lops
dag = new Dag<>();
// check there are actually Lops in to process (loop stmt body will not have any)
if (sb.getLops() != null && !sb.getLops().isEmpty()) {
for (Lop l : sb.getLops()) {
l.addToDag(dag);
}
// Instructions for Lops DAGs
instruct = dag.getJobs(sb, config);
rtpb.addInstructions(instruct);
}
retPB = rtpb;
// post processing for generating missing instructions
// retPB = verifyAndCorrectProgramBlock(sb.liveIn(), sb.liveOut(), sb._kill, retPB);
// add statement block
retPB.setStatementBlock(sb);
// add location information
retPB.setParseInfo(sb);
}
return retPB;
}
Aggregations