Repository: incubator-systemml Updated Branches: refs/heads/master a929ae6e6 -> 0dd095ffb
[MINOR] Fix code generator (templates, existing ops, input ordering) Project: http://git-wip-us.apache.org/repos/asf/incubator-systemml/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-systemml/commit/0dd095ff Tree: http://git-wip-us.apache.org/repos/asf/incubator-systemml/tree/0dd095ff Diff: http://git-wip-us.apache.org/repos/asf/incubator-systemml/diff/0dd095ff Branch: refs/heads/master Commit: 0dd095ffb8a951ccdd52e889d3dcb4bfb2c95545 Parents: a929ae6 Author: Matthias Boehm <mboe...@gmail.com> Authored: Fri Mar 24 19:32:08 2017 -0700 Committer: Matthias Boehm <mboe...@gmail.com> Committed: Fri Mar 24 19:32:08 2017 -0700 ---------------------------------------------------------------------- .../sysml/hops/codegen/cplan/CNodeTernary.java | 2 +- .../sysml/hops/codegen/template/CellTpl.java | 47 +++++++++++++++----- .../sysml/hops/codegen/template/RowAggTpl.java | 37 ++++++++++++--- .../hops/codegen/template/TemplateUtils.java | 9 ++-- .../sysml/runtime/codegen/SpoofOperator.java | 4 +- 5 files changed, 76 insertions(+), 23 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/0dd095ff/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeTernary.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeTernary.java b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeTernary.java index c9b389d..eb26eff 100644 --- a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeTernary.java +++ b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeTernary.java @@ -43,7 +43,7 @@ public class CNodeTernary extends CNode return " double %TMP% = %IN1% + %IN2% * %IN3%;\n" ; case MINUS_MULT: - return " double %TMP% = %IN1% - %IN2% * %IN3%;\n;\n" ; + return " double %TMP% = %IN1% - %IN2% * %IN3%;\n" ; case LOOKUP_RC1: return " double %TMP% = %IN1%[rowIndex*%IN2%+%IN3%-1];\n"; http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/0dd095ff/src/main/java/org/apache/sysml/hops/codegen/template/CellTpl.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/codegen/template/CellTpl.java b/src/main/java/org/apache/sysml/hops/codegen/template/CellTpl.java index c645eed..b919b6d 100644 --- a/src/main/java/org/apache/sysml/hops/codegen/template/CellTpl.java +++ b/src/main/java/org/apache/sysml/hops/codegen/template/CellTpl.java @@ -20,9 +20,11 @@ package org.apache.sysml.hops.codegen.template; import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; import org.apache.sysml.hops.AggBinaryOp; import org.apache.sysml.hops.AggUnaryOp; @@ -98,15 +100,12 @@ public class CellTpl extends BaseTpl rConstructCplan(hop, memo, tmp, inHops, compileLiterals); hop.resetVisitStatus(); - //reorder inputs (ensure matrices/vectors come first, prune literals) - LinkedList<Hop> sinHops = new LinkedList<Hop>(); - for( int i : new int[]{0,1,2} ) //matrices, vectors, scalars - for( Hop h : inHops ) //matrices - if( (i==0 && h.getDataType().isMatrix() && !TemplateUtils.isVector(h)) - || (i==1 && h.getDataType().isMatrix() && TemplateUtils.isVector(h)) - || (i==2 && h.getDataType().isScalar() && !tmp.get(h.getHopID()).isLiteral())) { - sinHops.add(h); - } + //reorder inputs (ensure matrices/vectors come first) and prune literals + //note: we order by number of cells and subsequently sparsity to ensure + //that sparse inputs are used as the main input w/o unnecessary conversion + List<Hop> sinHops = inHops.stream() + .filter(h -> !(h.getDataType().isScalar() && tmp.get(h.getHopID()).isLiteral())) + .sorted(new HopInputComparator()).collect(Collectors.toList()); //construct template node ArrayList<CNode> inputs = new ArrayList<CNode>(); @@ -115,8 +114,8 @@ public class CellTpl extends BaseTpl CNode output = tmp.get(hop.getHopID()); CNodeCell tpl = new CNodeCell(inputs, output); tpl.setCellType(TemplateUtils.getCellType(hop)); - tpl.setSparseSafe((HopRewriteUtils.isBinary(hop, OpOp2.MULT) && hop.getInput().contains(sinHops.getFirst())) - || (HopRewriteUtils.isBinary(hop, OpOp2.DIV) && hop.getInput().get(0) == sinHops.getFirst())); + tpl.setSparseSafe((HopRewriteUtils.isBinary(hop, OpOp2.MULT) && hop.getInput().contains(sinHops.get(0))) + || (HopRewriteUtils.isBinary(hop, OpOp2.DIV) && hop.getInput().get(0) == sinHops.get(0))); tpl.setRequiresCastDtm(hop instanceof AggBinaryOp); // return cplan instance @@ -278,4 +277,28 @@ public class CellTpl extends BaseTpl || isBinaryMatrixScalar || isBinaryMatrixVector || isBinaryMatrixMatrixDense || isTernaryVectorScalarVector || isTernaryMatrixScalarMatrixDense); } + + /** + * Comparator to order input hops of the cell template. We try to order + * matrices-vectors-scalars via sorting by number of cells and for + * equal number of cells by sparsity to prefer sparse inputs as the main + * input for sparsity exploitation. + */ + public static class HopInputComparator implements Comparator<Hop> + { + @Override + public int compare(Hop h1, Hop h2) { + long ncells1 = h1.getDataType()==DataType.SCALAR ? Long.MIN_VALUE : + h1.dimsKnown() ? h1.getDim1()*h1.getDim2() : Long.MAX_VALUE; + long ncells2 = h2.getDataType()==DataType.SCALAR ? Long.MIN_VALUE : + h2.dimsKnown() ? h2.getDim1()*h2.getDim2() : Long.MAX_VALUE; + if( ncells1 > ncells2 ) + return -1; + else if( ncells1 < ncells2) + return 1; + return Long.compare( + h1.dimsKnown(true) ? h1.getNnz() : ncells1, + h2.dimsKnown(true) ? h2.getNnz() : ncells2); + } + } } http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/0dd095ff/src/main/java/org/apache/sysml/hops/codegen/template/RowAggTpl.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/codegen/template/RowAggTpl.java b/src/main/java/org/apache/sysml/hops/codegen/template/RowAggTpl.java index 1aa380b..c16c831 100644 --- a/src/main/java/org/apache/sysml/hops/codegen/template/RowAggTpl.java +++ b/src/main/java/org/apache/sysml/hops/codegen/template/RowAggTpl.java @@ -20,9 +20,11 @@ package org.apache.sysml.hops.codegen.template; import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; import org.apache.sysml.hops.AggBinaryOp; import org.apache.sysml.hops.AggUnaryOp; @@ -100,10 +102,10 @@ public class RowAggTpl extends BaseTpl { rConstructCplan(hop, memo, tmp, inHops, inHops2, compileLiterals); hop.resetVisitStatus(); - //reorder inputs (ensure matrix is first input) - LinkedList<Hop> sinHops = new LinkedList<Hop>(inHops); - Hop X = inHops2.get("X"); - sinHops.remove(X); sinHops.addFirst(X); + //reorder inputs (ensure matrix is first input, and other inputs ordered by size) + List<Hop> sinHops = inHops.stream() + .filter(h -> !(h.getDataType().isScalar() && tmp.get(h.getHopID()).isLiteral())) + .sorted(new HopInputComparator(inHops2.get("X"))).collect(Collectors.toList()); //construct template node ArrayList<CNode> inputs = new ArrayList<CNode>(); @@ -216,4 +218,29 @@ public class RowAggTpl extends BaseTpl { tmp.put(hop.getHopID(), out); } + + /** + * Comparator to order input hops of the row aggregate template. We try + * to order matrices-vectors-scalars via sorting by number of cells but + * we keep the given main input always at the first position. + */ + public static class HopInputComparator implements Comparator<Hop> + { + private final Hop _X; + + public HopInputComparator(Hop X) { + _X = X; + } + + @Override + public int compare(Hop h1, Hop h2) { + long ncells1 = h1.getDataType()==DataType.SCALAR ? Long.MIN_VALUE : + (h1==_X) ? Long.MAX_VALUE : + h1.dimsKnown() ? h1.getDim1()*h1.getDim2() : Long.MAX_VALUE-1; + long ncells2 = h2.getDataType()==DataType.SCALAR ? Long.MIN_VALUE : + (h2==_X) ? Long.MAX_VALUE : + h2.dimsKnown() ? h2.getDim1()*h2.getDim2() : Long.MAX_VALUE-1; + return (ncells1 > ncells2) ? -1 : (ncells1 < ncells2) ? 1 : 0; + } + } } http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/0dd095ff/src/main/java/org/apache/sysml/hops/codegen/template/TemplateUtils.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/codegen/template/TemplateUtils.java b/src/main/java/org/apache/sysml/hops/codegen/template/TemplateUtils.java index 862c4f6..6c2fe8d 100644 --- a/src/main/java/org/apache/sysml/hops/codegen/template/TemplateUtils.java +++ b/src/main/java/org/apache/sysml/hops/codegen/template/TemplateUtils.java @@ -254,13 +254,16 @@ public class TemplateUtils public static boolean hasSingleOperation(CNodeTpl tpl) { CNode output = tpl.getOutput(); return (output instanceof CNodeUnary || output instanceof CNodeBinary - || output instanceof CNodeTernary) && hasOnlyDataNodeInputs(output); + || output instanceof CNodeTernary) && hasOnlyDataNodeOrLookupInputs(output); } - public static boolean hasOnlyDataNodeInputs(CNode node) { + public static boolean hasOnlyDataNodeOrLookupInputs(CNode node) { boolean ret = true; for( CNode c : node.getInput() ) - ret &= (c instanceof CNodeData); + ret &= (c instanceof CNodeData || (c instanceof CNodeUnary + && (((CNodeUnary)c).getType()==UnaryType.LOOKUP0 + || ((CNodeUnary)c).getType()==UnaryType.LOOKUP_R + || ((CNodeUnary)c).getType()==UnaryType.LOOKUP_RC))); return ret; } } http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/0dd095ff/src/main/java/org/apache/sysml/runtime/codegen/SpoofOperator.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/codegen/SpoofOperator.java b/src/main/java/org/apache/sysml/runtime/codegen/SpoofOperator.java index 8cb6692..6142396 100644 --- a/src/main/java/org/apache/sysml/runtime/codegen/SpoofOperator.java +++ b/src/main/java/org/apache/sysml/runtime/codegen/SpoofOperator.java @@ -72,8 +72,8 @@ public abstract class SpoofOperator implements Serializable || inputs.get(i).isInSparseFormat() ) { MatrixBlock tmp = inputs.get(i); b[i-offset] = DataConverter.convertToDoubleVector(tmp); - LOG.warn("Converted "+tmp.getNumRows()+"x"+tmp.getNumColumns() + - " sideways input matrix from sparse to dense."); + LOG.warn(getClass().getName()+": Converted "+tmp.getNumRows()+"x"+tmp.getNumColumns()+ + ", nnz="+tmp.getNonZeros()+" sideways input matrix from sparse to dense."); } //use existing dense block else {