Repository: incubator-systemml Updated Branches: refs/heads/master d65c7b5bb -> 8936e4f8a
[SYSTEMML-1297] Extended explain tool for code generation plans This patch extends the existing explain tool for code generation plans (cplans). In order to provide a useful explain output, we also extended the cnode base with individual ids, dag handling, and operation codes. Furthermore, the explain of code generation plans and source code has been fully integrated with the various explain types. Project: http://git-wip-us.apache.org/repos/asf/incubator-systemml/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-systemml/commit/e449cae6 Tree: http://git-wip-us.apache.org/repos/asf/incubator-systemml/tree/e449cae6 Diff: http://git-wip-us.apache.org/repos/asf/incubator-systemml/diff/e449cae6 Branch: refs/heads/master Commit: e449cae627cf5b0ea601cde5349c16b425724560 Parents: d65c7b5 Author: Matthias Boehm <mboe...@gmail.com> Authored: Sat Mar 4 20:37:15 2017 -0800 Committer: Matthias Boehm <mboe...@gmail.com> Committed: Sat Mar 4 20:44:26 2017 -0800 ---------------------------------------------------------------------- .../sysml/hops/codegen/SpoofCompiler.java | 25 +++--- .../apache/sysml/hops/codegen/cplan/CNode.java | 34 +++++++- .../sysml/hops/codegen/cplan/CNodeBinary.java | 14 +++- .../sysml/hops/codegen/cplan/CNodeCell.java | 10 +++ .../sysml/hops/codegen/cplan/CNodeData.java | 2 +- .../hops/codegen/cplan/CNodeOuterProduct.java | 10 +++ .../hops/codegen/cplan/CNodeRowAggVector.java | 7 ++ .../sysml/hops/codegen/cplan/CNodeTpl.java | 9 +++ .../sysml/hops/codegen/cplan/CNodeUnary.java | 8 +- .../apache/sysml/hops/recompile/Recompiler.java | 2 +- .../java/org/apache/sysml/utils/Explain.java | 85 +++++++++++++++++++- .../functions/codegen/DAGCellwiseTmplTest.java | 2 +- .../functions/codegen/SumProductChainTest.java | 2 +- 13 files changed, 188 insertions(+), 22 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/e449cae6/src/main/java/org/apache/sysml/hops/codegen/SpoofCompiler.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/codegen/SpoofCompiler.java b/src/main/java/org/apache/sysml/hops/codegen/SpoofCompiler.java index 760eff0..f40a883 100644 --- a/src/main/java/org/apache/sysml/hops/codegen/SpoofCompiler.java +++ b/src/main/java/org/apache/sysml/hops/codegen/SpoofCompiler.java @@ -62,7 +62,6 @@ import org.apache.sysml.runtime.codegen.CodegenUtils; import org.apache.sysml.runtime.codegen.SpoofCellwise.CellType; import org.apache.sysml.runtime.matrix.data.Pair; import org.apache.sysml.utils.Explain; -import org.apache.sysml.utils.Explain.ExplainType; import org.apache.sysml.utils.Statistics; public class SpoofCompiler @@ -152,7 +151,7 @@ public class SpoofCompiler if( roots == null ) return roots; - ArrayList<Hop> optimized = SpoofCompiler.optimize(roots, true); + ArrayList<Hop> optimized = SpoofCompiler.optimize(roots, false); Hop.resetVisitStatus(roots); Hop.resetVisitStatus(optimized); @@ -164,15 +163,15 @@ public class SpoofCompiler * Main interface of sum-product optimizer, predicate dag. * * @param root dag root node - * @param compileLiterals if true literals compiled as constants, otherwise as scalar variables + * @param recompile true if invoked during dynamic recompilation * @return dag root node of modified dag * @throws DMLRuntimeException if optimization failed */ - public static Hop optimize( Hop root, boolean compileLiterals ) throws DMLRuntimeException { + public static Hop optimize( Hop root, boolean recompile ) throws DMLRuntimeException { if( root == null ) return root; - return optimize(new ArrayList<Hop>(Arrays.asList(root)), compileLiterals).get(0); + return optimize(new ArrayList<Hop>(Arrays.asList(root)), recompile).get(0); } public static void cleanupCodeGenerator() { @@ -186,12 +185,12 @@ public class SpoofCompiler * Main interface of sum-product optimizer, statement block dag. * * @param roots dag root nodes - * @param compileLiterals if true literals compiled as constants, otherwise as scalar variables + * @param recompile true if invoked during dynamic recompilation * @return dag root nodes of modified dag * @throws DMLRuntimeException if optimization failed */ @SuppressWarnings("unused") - public static ArrayList<Hop> optimize(ArrayList<Hop> roots, boolean compileLiterals) + public static ArrayList<Hop> optimize(ArrayList<Hop> roots, boolean recompile) throws DMLRuntimeException { if( roots == null || roots.isEmpty() || !OPTIMIZE ) @@ -202,6 +201,9 @@ public class SpoofCompiler try { + //context-sensitive literal replacement (only integers during recompile) + boolean compileLiterals = ALWAYS_COMPILE_LITERALS || !recompile; + //construct codegen plans HashMap<Long, Pair<Hop[],CNodeTpl>> cplans = constructCPlans(roots, compileLiterals); @@ -223,8 +225,13 @@ public class SpoofCompiler //generate java source code String src = tmp.getValue().codegen(false); - //explain debug output generated source code - if( LDEBUG || DMLScript.EXPLAIN != ExplainType.NONE ) { + //explain debug output cplans or generated source code + if( LDEBUG || DMLScript.EXPLAIN.isHopsType(recompile) ) { + LOG.info("Codegen EXPLAIN (generated cplan for HopID: " + cplan.getKey() +"):"); + LOG.info(tmp.getValue().getClassname() + +Explain.explainCPlan(cplan.getValue().getValue())); + } + if( LDEBUG || DMLScript.EXPLAIN.isRuntimeType(recompile) ) { LOG.info("Codegen EXPLAIN (generated code for HopID: " + cplan.getKey() +"):"); LOG.info(src); } http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/e449cae6/src/main/java/org/apache/sysml/hops/codegen/cplan/CNode.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNode.java b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNode.java index ac276b6..446da32 100644 --- a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNode.java +++ b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNode.java @@ -27,10 +27,13 @@ import org.apache.sysml.runtime.controlprogram.parfor.util.IDSequence; public abstract class CNode { - private static final IDSequence _seq = new IDSequence(); + private static final IDSequence _seqVar = new IDSequence(); + private static final IDSequence _seqID = new IDSequence(); + protected final long _ID; protected ArrayList<CNode> _inputs = null; protected CNode _output = null; + protected boolean _visited = false; protected boolean _generated = false; protected String _genVar = null; protected long _rows = -1; @@ -43,21 +46,26 @@ public abstract class CNode protected int _hash = 0; public CNode() { + _ID = _seqID.getNextID(); _inputs = new ArrayList<CNode>(); _generated = false; } + + public long getID() { + return _ID; + } public ArrayList<CNode> getInput() { return _inputs; } public String createVarname() { - _genVar = "TMP"+_seq.getNextID(); + _genVar = "TMP"+_seqVar.getNextID(); return _genVar; } protected String getCurrentVarName() { - return "TMP"+(_seq.getCurrentID()-1); + return "TMP"+(_seqVar.getCurrentID()-1); } public String getVarname() { @@ -118,6 +126,26 @@ public abstract class CNode _hash = 0; } + public boolean isVisited() { + return _visited; + } + + public void setVisited() { + setVisited(true); + } + + public void setVisited(boolean flag) { + _visited = flag; + } + + public void resetVisitStatus() { + if( !isVisited() ) + return; + for( CNode h : getInput() ) + h.resetVisitStatus(); + setVisited(false); + } + public abstract String codegen(boolean sparse) ; public abstract void setOutputDims(); http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/e449cae6/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeBinary.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeBinary.java b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeBinary.java index fcd2d16..9da9915 100644 --- a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeBinary.java +++ b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeBinary.java @@ -181,10 +181,20 @@ public class CNodeBinary extends CNode case VECT_DIV_ADD: return "b(vda)"; case MULT: return "b(*)"; case DIV: return "b(/)"; + case PLUS: return "b(+)"; + case MINUS: return "b(-)"; + case MODULUS: return "b(%%)"; + case INTDIV: return "b(%/%)"; + case LESS: return "b(<)"; + case LESSEQUAL: return "b(<=)"; + case GREATER: return "b(>)"; + case GREATEREQUAL: return "b(>=)"; + case EQUAL: return "b(==)"; + case NOTEQUAL: return "b(!=)"; + case MINUS1_MULT: return "b(1-*)"; case VECT_DIV_SCALAR: return "b(vector/)"; case VECT_MULT_SCALAR: return "b(vector*)"; - default: - return super.toString(); + default: return "b("+_type.name()+")"; } } http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/e449cae6/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeCell.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeCell.java b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeCell.java index 9fdaa62..db278e4 100644 --- a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeCell.java +++ b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeCell.java @@ -141,4 +141,14 @@ public class CNodeCell extends CNodeTpl return super.equals(that) && _type == that._type; } + + @Override + public String getTemplateInfo() { + StringBuilder sb = new StringBuilder(); + sb.append("SPOOF CELLWISE [type="); + sb.append(_type.name()); + sb.append(", mc="+_multipleConsumers); + sb.append("]"); + return sb.toString(); + } } http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/e449cae6/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeData.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeData.java b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeData.java index d5457e8..6bf760f 100644 --- a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeData.java +++ b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeData.java @@ -72,7 +72,7 @@ public class CNodeData extends CNode @Override public String toString() { - return "CdataNode[name="+_name+", id="+_hopID+"]"; + return "data("+_name+", hopid="+_hopID+")"; } @Override http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/e449cae6/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeOuterProduct.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeOuterProduct.java b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeOuterProduct.java index 6a543cc..addc20b 100644 --- a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeOuterProduct.java +++ b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeOuterProduct.java @@ -162,4 +162,14 @@ public class CNodeOuterProduct extends CNodeTpl && _type == that._type && _transposeOutput == that._transposeOutput; } + + @Override + public String getTemplateInfo() { + StringBuilder sb = new StringBuilder(); + sb.append("SPOOF OUTERPRODUCT [type="); + sb.append(_type.name()); + sb.append(", to="+_transposeOutput); + sb.append("]"); + return sb.toString(); + } } http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/e449cae6/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeRowAggVector.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeRowAggVector.java b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeRowAggVector.java index 09967aa..d3a39e3 100644 --- a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeRowAggVector.java +++ b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeRowAggVector.java @@ -108,4 +108,11 @@ public class CNodeRowAggVector extends CNodeTpl return (o instanceof CNodeRowAggVector && super.equals(o)); } + + @Override + public String getTemplateInfo() { + StringBuilder sb = new StringBuilder(); + sb.append("SPOOF ROWAGGREGATE"); + return sb.toString(); + } } http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/e449cae6/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeTpl.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeTpl.java b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeTpl.java index 343aba4..df20b4d 100644 --- a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeTpl.java +++ b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeTpl.java @@ -55,6 +55,13 @@ public abstract class CNodeTpl extends CNode implements Cloneable _inputs = tmp; } + public String[] getInputNames() { + String[] ret = new String[_inputs.size()]; + for( int i=0; i<_inputs.size(); i++ ) + ret[i] = _inputs.get(i).getVarname(); + return ret; + } + public String codegen() { return codegen(false); } @@ -63,6 +70,8 @@ public abstract class CNodeTpl extends CNode implements Cloneable public abstract SpoofOutputDimsType getOutputDimType(); + public abstract String getTemplateInfo(); + protected void renameInputs(ArrayList<CNode> inputs, int startIndex) { //create map of hopID to data nodes with new names, used for CSE HashMap<Long, CNode> nodes = new HashMap<Long, CNode>(); http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/e449cae6/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeUnary.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeUnary.java b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeUnary.java index f491609..5d4c63e 100644 --- a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeUnary.java +++ b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeUnary.java @@ -156,9 +156,11 @@ public class CNodeUnary extends CNode @Override public String toString() { switch(_type) { - case ROW_SUMS: return "u(R+)"; - default: - return super.toString(); + case ROW_SUMS: return "u(R+)"; + case LOOKUP_R: return "u(ixr)"; + case LOOKUP_RC: return "u(ixrc)"; + case LOOKUP0: return "u(ix0)"; + default: return "u("+_type.name()+")"; } } http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/e449cae6/src/main/java/org/apache/sysml/hops/recompile/Recompiler.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/recompile/Recompiler.java b/src/main/java/org/apache/sysml/hops/recompile/Recompiler.java index da13d0a..f8b2a62 100644 --- a/src/main/java/org/apache/sysml/hops/recompile/Recompiler.java +++ b/src/main/java/org/apache/sysml/hops/recompile/Recompiler.java @@ -215,7 +215,7 @@ public class Recompiler // codegen if enabled if( ConfigurationManager.getDMLConfig().getBooleanValue(DMLConfig.CODEGEN) && SpoofCompiler.RECOMPILE ) { Hop.resetVisitStatus(hops); - hops = SpoofCompiler.optimize(hops, SpoofCompiler.ALWAYS_COMPILE_LITERALS); + hops = SpoofCompiler.optimize(hops, true); } // construct lops http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/e449cae6/src/main/java/org/apache/sysml/utils/Explain.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/utils/Explain.java b/src/main/java/org/apache/sysml/utils/Explain.java index ccc9853..a03ad73 100644 --- a/src/main/java/org/apache/sysml/utils/Explain.java +++ b/src/main/java/org/apache/sysml/utils/Explain.java @@ -32,6 +32,8 @@ import org.apache.sysml.hops.Hop.VisitStatus; import org.apache.sysml.hops.HopsException; import org.apache.sysml.hops.LiteralOp; import org.apache.sysml.hops.OptimizerUtils; +import org.apache.sysml.hops.codegen.cplan.CNode; +import org.apache.sysml.hops.codegen.cplan.CNodeTpl; import org.apache.sysml.hops.globalopt.gdfgraph.GDFLoopNode; import org.apache.sysml.hops.globalopt.gdfgraph.GDFNode; import org.apache.sysml.hops.globalopt.gdfgraph.GDFNode.NodeType; @@ -85,7 +87,14 @@ public class Explain HOPS, // explain program and hops RUNTIME, // explain runtime program (default) RECOMPILE_HOPS, // explain hops, incl recompile - RECOMPILE_RUNTIME, // explain runtime program, incl recompile + RECOMPILE_RUNTIME; // explain runtime program, incl recompile + + public boolean isHopsType(boolean recompile) { + return (this==RECOMPILE_HOPS || (!recompile && this==HOPS)); + } + public boolean isRuntimeType(boolean recompile) { + return (this==RECOMPILE_RUNTIME || (!recompile && this==RUNTIME)); + } }; public static class ExplainCounts { @@ -359,6 +368,34 @@ public class Explain return ret; } + + public static String explainCPlan( CNodeTpl cplan ) + throws DMLRuntimeException + { + StringBuilder sb = new StringBuilder(); + + //create template header + sb.append("\n----------------------------------------\n"); + sb.append("CPLAN: "+cplan.getTemplateInfo()+"\n"); + sb.append("--inputs: "+Arrays.toString(cplan.getInputNames())+"\n"); + sb.append("----------------------------------------\n"); + + //explain body dag + cplan.getOutput().resetVisitStatus(); + sb.append(explainCNode(cplan.getOutput(), 1)); + cplan.getOutput().resetVisitStatus(); + sb.append("----------------------------------------\n"); + + return sb.toString(); + } + + public static String explain( CNode node ) throws DMLRuntimeException { + return explain(node, 0); + } + + public static String explain( CNode node, int level ) throws DMLRuntimeException { + return explainCNode(node, level); + } public static String explainGDFNodes( ArrayList<GDFNode> gdfnodes ) throws DMLRuntimeException @@ -601,6 +638,52 @@ public class Explain } ////////////// + // internal explain CNODE + + private static String explainCNode(CNode cnode, int level) + throws DMLRuntimeException + { + if( cnode.isVisited() ) + return ""; + + StringBuilder sb = new StringBuilder(); + String offset = createOffset(level); + + for( CNode input : cnode.getInput() ) + sb.append(explainCNode(input, level)); + + //indentation + sb.append(offset); + + //hop id + if( SHOW_DATA_DEPENDENCIES ) + sb.append("("+cnode.getID()+") "); + + //operation string + sb.append(cnode.toString()); + + //input hop references + if( SHOW_DATA_DEPENDENCIES ) { + StringBuilder childs = new StringBuilder(); + childs.append(" ("); + boolean childAdded = false; + for( CNode input : cnode.getInput() ) { + childs.append(childAdded?",":""); + childs.append(input.getID()); + childAdded = true; + } + childs.append(")"); + if( childAdded ) + sb.append(childs.toString()); + } + + sb.append('\n'); + cnode.setVisited(); + + return sb.toString(); + } + + ////////////// // internal explain GDFNODE /** http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/e449cae6/src/test/java/org/apache/sysml/test/integration/functions/codegen/DAGCellwiseTmplTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/sysml/test/integration/functions/codegen/DAGCellwiseTmplTest.java b/src/test/java/org/apache/sysml/test/integration/functions/codegen/DAGCellwiseTmplTest.java index 65be916..cb2f480 100644 --- a/src/test/java/org/apache/sysml/test/integration/functions/codegen/DAGCellwiseTmplTest.java +++ b/src/test/java/org/apache/sysml/test/integration/functions/codegen/DAGCellwiseTmplTest.java @@ -135,7 +135,7 @@ public class DAGCellwiseTmplTest extends AutomatedTestBase String HOME = SCRIPT_DIR + TEST_DIR; fullDMLScriptName = HOME + testname + ".dml"; - programArgs = new String[]{"-explain", "runtime", "-stats", + programArgs = new String[]{"-explain", "hops", "-stats", "-config=" + HOME + TEST_CONF, "-args", String.valueOf(cols), output("S") }; fullRScriptName = HOME + testname + ".R"; http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/e449cae6/src/test/java/org/apache/sysml/test/integration/functions/codegen/SumProductChainTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/sysml/test/integration/functions/codegen/SumProductChainTest.java b/src/test/java/org/apache/sysml/test/integration/functions/codegen/SumProductChainTest.java index 2ba9ffa..35dfa82 100644 --- a/src/test/java/org/apache/sysml/test/integration/functions/codegen/SumProductChainTest.java +++ b/src/test/java/org/apache/sysml/test/integration/functions/codegen/SumProductChainTest.java @@ -118,7 +118,7 @@ public class SumProductChainTest extends AutomatedTestBase String HOME = SCRIPT_DIR + TEST_DIR; fullDMLScriptName = HOME + testname + ".dml"; - programArgs = new String[]{"-explain", "-stats", + programArgs = new String[]{"-explain", "hops", "-stats", "-config=" + HOME + TEST_CONF, "-args", input("X"), output("R") }; fullRScriptName = HOME + testname + ".R";