[SYSTEMML-1963] Fix missing codegen dense-sparse vector primitives This patch fixes issues that showed up with the fuse-all heuristic on different scenarios of ALS-CG. In particular, this adds missing vector primitives for dense-sparse vector operations and modifies the code generator accordingly. Most of these operations are invariant to the ordering of inputs and hence simply call the existing primitives with permuted inputs.
Project: http://git-wip-us.apache.org/repos/asf/systemml/repo Commit: http://git-wip-us.apache.org/repos/asf/systemml/commit/b6b67727 Tree: http://git-wip-us.apache.org/repos/asf/systemml/tree/b6b67727 Diff: http://git-wip-us.apache.org/repos/asf/systemml/diff/b6b67727 Branch: refs/heads/master Commit: b6b67727b9ec271995520e47dc3044eccaed2b65 Parents: 06b4b9d Author: Matthias Boehm <mboe...@gmail.com> Authored: Sun Oct 15 20:27:51 2017 -0700 Committer: Matthias Boehm <mboe...@gmail.com> Committed: Sun Oct 15 20:27:51 2017 -0700 ---------------------------------------------------------------------- .../sysml/hops/codegen/cplan/CNodeBinary.java | 33 ++++----- .../runtime/codegen/LibSpoofPrimitives.java | 70 ++++++++++++++++++++ 2 files changed, 88 insertions(+), 15 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/systemml/blob/b6b67727/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 1ca4aa6..cac8ab8 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 @@ -68,16 +68,16 @@ public class CNodeBinary extends CNode return ssComm || vsComm || vvComm; } - public String getTemplate(boolean sparse, boolean scalarVector, boolean scalarInput) { + public String getTemplate(boolean sparseLhs, boolean sparseRhs, boolean scalarVector, boolean scalarInput) { switch (this) { case DOT_PRODUCT: - return sparse ? " double %TMP% = LibSpoofPrimitives.dotProduct(%IN1v%, %IN2%, %IN1i%, %POS1%, %POS2%, alen);\n" : + return sparseLhs ? " double %TMP% = LibSpoofPrimitives.dotProduct(%IN1v%, %IN2%, %IN1i%, %POS1%, %POS2%, alen);\n" : " double %TMP% = LibSpoofPrimitives.dotProduct(%IN1%, %IN2%, %POS1%, %POS2%, %LEN%);\n"; case VECT_MATRIXMULT: - return sparse ? " double[] %TMP% = LibSpoofPrimitives.vectMatrixMult(%IN1v%, %IN2%, %IN1i%, %POS1%, %POS2%, alen, len);\n" : + return sparseLhs ? " double[] %TMP% = LibSpoofPrimitives.vectMatrixMult(%IN1v%, %IN2%, %IN1i%, %POS1%, %POS2%, alen, len);\n" : " double[] %TMP% = LibSpoofPrimitives.vectMatrixMult(%IN1%, %IN2%, %POS1%, %POS2%, %LEN%);\n"; case VECT_OUTERMULT_ADD: - return sparse ? " LibSpoofPrimitives.vectOuterMultAdd(%IN1v%, %IN2%, %OUT%, %IN1i%, %POS1%, %POS2%, %POSOUT%, alen, %LEN1%, %LEN2%);\n" : + return sparseLhs ? " LibSpoofPrimitives.vectOuterMultAdd(%IN1v%, %IN2%, %OUT%, %IN1i%, %POS1%, %POS2%, %POSOUT%, alen, %LEN1%, %LEN2%);\n" : " LibSpoofPrimitives.vectOuterMultAdd(%IN1%, %IN2%, %OUT%, %POS1%, %POS2%, %POSOUT%, %LEN1%, %LEN2%);\n"; //vector-scalar-add operations @@ -96,10 +96,10 @@ public class CNodeBinary extends CNode case VECT_GREATEREQUAL_ADD: { String vectName = getVectorPrimitiveName(); if( scalarVector ) - return sparse ? " LibSpoofPrimitives.vect"+vectName+"Add(%IN1%, %IN2v%, %OUT%, %IN2i%, %POS2%, %POSOUT%, alen, %LEN%);\n" : + return sparseLhs ? " LibSpoofPrimitives.vect"+vectName+"Add(%IN1%, %IN2v%, %OUT%, %IN2i%, %POS2%, %POSOUT%, alen, %LEN%);\n" : " LibSpoofPrimitives.vect"+vectName+"Add(%IN1%, %IN2%, %OUT%, %POS2%, %POSOUT%, %LEN%);\n"; else - return sparse ? " LibSpoofPrimitives.vect"+vectName+"Add(%IN1v%, %IN2%, %OUT%, %IN1i%, %POS1%, %POSOUT%, alen, %LEN%);\n" : + return sparseLhs ? " LibSpoofPrimitives.vect"+vectName+"Add(%IN1v%, %IN2%, %OUT%, %IN1i%, %POS1%, %POSOUT%, alen, %LEN%);\n" : " LibSpoofPrimitives.vect"+vectName+"Add(%IN1%, %IN2%, %OUT%, %POS1%, %POSOUT%, %LEN%);\n"; } @@ -119,10 +119,10 @@ public class CNodeBinary extends CNode case VECT_GREATEREQUAL_SCALAR: { String vectName = getVectorPrimitiveName(); if( scalarVector ) - return sparse ? " double[] %TMP% = LibSpoofPrimitives.vect"+vectName+"Write(%IN1%, %IN2v%, %IN2i%, %POS2%, alen, %LEN%);\n" : + return sparseLhs ? " double[] %TMP% = LibSpoofPrimitives.vect"+vectName+"Write(%IN1%, %IN2v%, %IN2i%, %POS2%, alen, %LEN%);\n" : " double[] %TMP% = LibSpoofPrimitives.vect"+vectName+"Write(%IN1%, %IN2%, %POS2%, %LEN%);\n"; else - return sparse ? " double[] %TMP% = LibSpoofPrimitives.vect"+vectName+"Write(%IN1v%, %IN2%, %IN1i%, %POS1%, alen, %LEN%);\n" : + return sparseLhs ? " double[] %TMP% = LibSpoofPrimitives.vect"+vectName+"Write(%IN1v%, %IN2%, %IN1i%, %POS1%, alen, %LEN%);\n" : " double[] %TMP% = LibSpoofPrimitives.vect"+vectName+"Write(%IN1%, %IN2%, %POS1%, %LEN%);\n"; } @@ -130,7 +130,7 @@ public class CNodeBinary extends CNode if( scalarInput ) return " double[] %TMP% = LibSpoofPrimitives.vectCBindWrite(%IN1%, %IN2%);\n"; else - return sparse ? + return sparseLhs ? " double[] %TMP% = LibSpoofPrimitives.vectCBindWrite(%IN1v%, %IN2%, %IN1i%, %POS1%, alen, %LEN%);\n" : " double[] %TMP% = LibSpoofPrimitives.vectCBindWrite(%IN1%, %IN2%, %POS1%, %LEN%);\n"; @@ -140,7 +140,7 @@ public class CNodeBinary extends CNode case VECT_MINUS: case VECT_PLUS: case VECT_MIN: - case VECT_MAX: + case VECT_MAX: case VECT_EQUAL: case VECT_NOTEQUAL: case VECT_LESS: @@ -148,8 +148,10 @@ public class CNodeBinary extends CNode case VECT_GREATER: case VECT_GREATEREQUAL: { String vectName = getVectorPrimitiveName(); - return sparse ? + return sparseLhs ? " double[] %TMP% = LibSpoofPrimitives.vect"+vectName+"Write(%IN1v%, %IN2%, %IN1i%, %POS1%, %POS2%, alen, %LEN%);\n" : + sparseRhs ? + " double[] %TMP% = LibSpoofPrimitives.vect"+vectName+"Write(%IN1%, %IN2v%, %POS1%, %IN2i%, %POS2%, alen, %LEN%);\n" : " double[] %TMP% = LibSpoofPrimitives.vect"+vectName+"Write(%IN1%, %IN2%, %POS1%, %POS2%, %LEN%);\n"; } @@ -269,14 +271,15 @@ public class CNodeBinary extends CNode sb.append(_inputs.get(1).codegen(sparse)); //generate binary operation (use sparse template, if data input) - boolean lsparse = sparse - && ((_inputs.get(0) instanceof CNodeData && _inputs.get(0).getVarname().startsWith("a")) - ||(_inputs.get(1) instanceof CNodeData && _inputs.get(1).getVarname().startsWith("a"))); + boolean lsparseLhs = sparse && _inputs.get(0) instanceof CNodeData + && _inputs.get(0).getVarname().startsWith("a"); + boolean lsparseRhs = sparse && _inputs.get(1) instanceof CNodeData + && _inputs.get(1).getVarname().startsWith("a"); boolean scalarInput = _inputs.get(0).getDataType().isScalar(); boolean scalarVector = (_inputs.get(0).getDataType().isScalar() && _inputs.get(1).getDataType().isMatrix()); String var = createVarname(); - String tmp = _type.getTemplate(lsparse, scalarVector, scalarInput); + String tmp = _type.getTemplate(lsparseLhs, lsparseRhs, scalarVector, scalarInput); tmp = tmp.replace("%TMP%", var); //replace input references and start indexes http://git-wip-us.apache.org/repos/asf/systemml/blob/b6b67727/src/main/java/org/apache/sysml/runtime/codegen/LibSpoofPrimitives.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/codegen/LibSpoofPrimitives.java b/src/main/java/org/apache/sysml/runtime/codegen/LibSpoofPrimitives.java index 6b4aad7..8444b5f 100644 --- a/src/main/java/org/apache/sysml/runtime/codegen/LibSpoofPrimitives.java +++ b/src/main/java/org/apache/sysml/runtime/codegen/LibSpoofPrimitives.java @@ -183,6 +183,11 @@ public class LibSpoofPrimitives return c; } + public static double[] vectMultWrite(double[] a, double[] b, int ai, int[] bix, int bi, int blen, int len) { + //invariant to the ordering of inputs + return vectMultWrite(b, a, bix, ai, bi, blen, len); + } + public static void vectWrite(double[] a, double[] c, int ci, int len) { if( a == null ) return; System.arraycopy(a, 0, c, ci, len); @@ -345,6 +350,18 @@ public class LibSpoofPrimitives return c; } + public static double[] vectDivWrite(double[] a, double[] b, int ai, int[] bix, int bi, int blen, int len) { + double[] c = allocVector(len, false); + for( int j = 0; j < len; j++ ) { + double aval = a[bi + j]; + c[j] = (aval==0) ? Double.NaN : (aval>0) ? + Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY; + } + for( int j = bi; j < bi+blen; j++ ) + c[bix[j]] = a[ai+bix[j]] / b[j]; + return c; + } + //custom vector minus public static void vectMinusAdd(double[] a, double bval, double[] c, int ai, int ci, int len) { @@ -417,6 +434,14 @@ public class LibSpoofPrimitives return c; } + public static double[] vectMinusWrite(double[] a, double[] b, int ai, int[] bix, int bi, int blen, int len) { + double[] c = allocVector(len, false); + System.arraycopy(a, ai, c, 0, len); + for( int j = bi; j < bi+blen; j++ ) + c[bix[j]] -= b[j]; + return c; + } + //custom vector plus public static void vectPlusAdd(double[] a, double bval, double[] c, int ai, int ci, int len) { @@ -475,6 +500,11 @@ public class LibSpoofPrimitives return c; } + public static double[] vectPlusWrite(double[] a, double[] b, int ai, int[] bix, int bi, int blen, int len) { + //invariant to the ordering of inputs + return vectPlusWrite(b, a, bix, bi, ai, blen, len); + } + //custom vector pow public static void vectPowAdd(double[] a, double bval, double[] c, int ai, int ci, int len) { @@ -600,6 +630,11 @@ public class LibSpoofPrimitives return c; } + public static double[] vectMinWrite(double[] a, double[] b, int ai, int[] bix, int bi, int blen, int len) { + //invariant to the ordering of inputs + return vectMinWrite(b, a, bix, bi, ai, blen, len); + } + //custom vector max public static void vectMaxAdd(double[] a, double bval, double[] c, int ai, int ci, int len) { @@ -661,6 +696,11 @@ public class LibSpoofPrimitives c[aix[j]] = Math.max(a[j], b[bi + aix[j]]); return c; } + + public static double[] vectMaxWrite(double[] a, double[] b, int ai, int[] bix, int bi, int blen, int len) { + //invariant to the ordering of inputs + return vectMaxWrite(b, a, bix, bi, ai, blen, len); + } //custom exp @@ -1385,6 +1425,11 @@ public class LibSpoofPrimitives return c; } + public static double[] vectEqualWrite(double[] a, double[] b, int ai, int[] bix, int bi, int blen, int len) { + //invariant to the ordering of inputs + return vectEqualWrite(b, a, bix, bi, ai, blen, len); + } + //custom vector not equal public static void vectNotequalAdd(double[] a, double bval, double[] c, int ai, int ci, int len) { @@ -1448,6 +1493,11 @@ public class LibSpoofPrimitives return c; } + public static double[] vectNotequalWrite(double[] a, double[] b, int ai, int[] bix, int bi, int blen, int len) { + //invariant to the ordering of inputs + return vectNotequalWrite(b, a, bix, bi, ai, blen, len); + } + //custom vector less public static void vectLessAdd(double[] a, double bval, double[] c, int ai, int ci, int len) { @@ -1511,6 +1561,11 @@ public class LibSpoofPrimitives return c; } + public static double[] vectLessWrite(double[] a, double[] b, int ai, int[] bix, int bi, int blen, int len) { + //invariant to the ordering of inputs + return vectGreaterequalWrite(b, a, bix, bi, ai, blen, len); + } + //custom vector less equal public static void vectLessequalAdd(double[] a, double bval, double[] c, int ai, int ci, int len) { @@ -1573,6 +1628,11 @@ public class LibSpoofPrimitives c[aix[j]] = (a[j] <= b[bi+aix[j]]) ? 1 : 0; return c; } + + public static double[] vectLessequalWrite(double[] a, double[] b, int ai, int[] bix, int bi, int blen, int len) { + //invariant to the ordering of inputs + return vectGreaterWrite(b, a, bix, bi, ai, blen, len); + } //custom vector greater @@ -1637,6 +1697,11 @@ public class LibSpoofPrimitives return c; } + public static double[] vectGreaterWrite(double[] a, double[] b, int ai, int[] bix, int bi, int blen, int len) { + //invariant to the ordering of inputs + return vectLessequalWrite(b, a, bix, bi, ai, blen, len); + } + //custom vector greater equal public static void vectGreaterequalAdd(double[] a, double bval, double[] c, int ai, int ci, int len) { @@ -1700,6 +1765,11 @@ public class LibSpoofPrimitives return c; } + public static double[] vectGreaterequalWrite(double[] a, double[] b, int ai, int[] bix, int bi, int blen, int len) { + //invariant to the ordering of inputs + return vectLessWrite(b, a, bix, bi, ai, blen, len); + } + //complex builtin functions that are not directly generated //(included here in order to reduce the number of imports)