You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@systemml.apache.org by mb...@apache.org on 2018/06/08 06:37:35 UTC
[1/2] systemml git commit: [SYSTEMML-2374] New simplification rewrite
'fold nary min/max ops'
Repository: systemml
Updated Branches:
refs/heads/master 5f580f02e -> 4d370a8a6
[SYSTEMML-2374] New simplification rewrite 'fold nary min/max ops'
This patch adds a new dynamic rewrite for folding nested binary or nary
min/max operations into a single nary min/max operation. Due to limited
support for broadcasting this is a dynamic rewrite that is only applied
if the dimensions of all involved matrix inputs match.
Project: http://git-wip-us.apache.org/repos/asf/systemml/repo
Commit: http://git-wip-us.apache.org/repos/asf/systemml/commit/8d320791
Tree: http://git-wip-us.apache.org/repos/asf/systemml/tree/8d320791
Diff: http://git-wip-us.apache.org/repos/asf/systemml/diff/8d320791
Branch: refs/heads/master
Commit: 8d320791265321de38050e741308e3243ce89a7b
Parents: 5f580f0
Author: Matthias Boehm <mb...@gmail.com>
Authored: Thu Jun 7 22:23:05 2018 -0700
Committer: Matthias Boehm <mb...@gmail.com>
Committed: Thu Jun 7 22:23:05 2018 -0700
----------------------------------------------------------------------
.../RewriteAlgebraicSimplificationDynamic.java | 57 ++++++++-
.../functions/misc/RewriteFoldMinMaxTest.java | 118 +++++++++++++++++++
.../scripts/functions/misc/RewriteFoldMax.dml | 28 +++++
.../scripts/functions/misc/RewriteFoldMin.dml | 28 +++++
.../functions/misc/ZPackageSuite.java | 1 +
5 files changed, 231 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/systemml/blob/8d320791/src/main/java/org/apache/sysml/hops/rewrite/RewriteAlgebraicSimplificationDynamic.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/rewrite/RewriteAlgebraicSimplificationDynamic.java b/src/main/java/org/apache/sysml/hops/rewrite/RewriteAlgebraicSimplificationDynamic.java
index 81c20e0..062da2f 100644
--- a/src/main/java/org/apache/sysml/hops/rewrite/RewriteAlgebraicSimplificationDynamic.java
+++ b/src/main/java/org/apache/sysml/hops/rewrite/RewriteAlgebraicSimplificationDynamic.java
@@ -22,6 +22,7 @@ package org.apache.sysml.hops.rewrite;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
+import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -37,11 +38,13 @@ import org.apache.sysml.hops.Hop.OpOp1;
import org.apache.sysml.hops.Hop.OpOp2;
import org.apache.sysml.hops.Hop.OpOp3;
import org.apache.sysml.hops.Hop.OpOp4;
+import org.apache.sysml.hops.Hop.OpOpN;
import org.apache.sysml.hops.Hop.ParamBuiltinOp;
import org.apache.sysml.hops.Hop.ReOrgOp;
import org.apache.sysml.hops.IndexingOp;
import org.apache.sysml.hops.LeftIndexingOp;
import org.apache.sysml.hops.LiteralOp;
+import org.apache.sysml.hops.NaryOp;
import org.apache.sysml.hops.OptimizerUtils;
import org.apache.sysml.hops.ParameterizedBuiltinOp;
import org.apache.sysml.hops.QuaternaryOp;
@@ -182,7 +185,7 @@ public class RewriteAlgebraicSimplificationDynamic extends HopRewriteRule
hi = simplifyWeightedUnaryMM(hop, hi, i); //e.g., X*exp(U%*%t(V)) -> wumm(X, U, t(V), exp)
hi = simplifyDotProductSum(hop, hi, i); //e.g., sum(v^2) -> t(v)%*%v if ncol(v)==1
hi = fuseSumSquared(hop, hi, i); //e.g., sum(X^2) -> sumSq(X), if ncol(X)>1
- hi = fuseAxpyBinaryOperationChain(hop, hi, i); //e.g., (X+s*Y) -> (X+*s Y), (X-s*Y) -> (X-*s Y)
+ hi = fuseAxpyBinaryOperationChain(hop, hi, i); //e.g., (X+s*Y) -> (X+*s Y), (X-s*Y) -> (X-*s Y)
}
hi = reorderMinusMatrixMult(hop, hi, i); //e.g., (-t(X))%*%y->-(t(X)%*%y), TODO size
hi = simplifySumMatrixMult(hop, hi, i); //e.g., sum(A%*%B) -> sum(t(colSums(A))*rowSums(B)), if not dot product / wsloss
@@ -191,6 +194,8 @@ public class RewriteAlgebraicSimplificationDynamic extends HopRewriteRule
hi = simplifyNnzComputation(hop, hi, i); //e.g., sum(ppred(X,0,"!=")) -> literal(nnz(X)), if nnz known
hi = simplifyNrowNcolComputation(hop, hi, i); //e.g., nrow(X) -> literal(nrow(X)), if nrow known to remove data dependency
hi = simplifyTableSeqExpand(hop, hi, i); //e.g., table(seq(1,nrow(v)), v, nrow(v), m) -> rexpand(v, max=m, dir=row, ignore=false, cast=true)
+ if( OptimizerUtils.ALLOW_OPERATOR_FUSION )
+ foldMultipleMinMaxOperations(hi); //e.g., min(X,min(min(3,7),Y)) -> min(X,3,7,Y)
//process childs recursively after rewrites (to investigate pattern newly created by rewrites)
if( !descendFirst )
@@ -2584,4 +2589,54 @@ public class RewriteAlgebraicSimplificationDynamic extends HopRewriteRule
return hi;
}
+
+ private static Hop foldMultipleMinMaxOperations(Hop hi)
+ {
+ if( (HopRewriteUtils.isBinary(hi, OpOp2.MIN, OpOp2.MAX)
+ || HopRewriteUtils.isNary(hi, OpOpN.MIN, OpOpN.MAX))
+ && !OptimizerUtils.isHadoopExecutionMode() )
+ {
+ OpOp2 bop = (hi instanceof BinaryOp) ? ((BinaryOp)hi).getOp() :
+ OpOp2.valueOf(((NaryOp)hi).getOp().name());
+ OpOpN nop = (hi instanceof NaryOp) ? ((NaryOp)hi).getOp() :
+ OpOpN.valueOf(((BinaryOp)hi).getOp().name());
+
+ boolean converged = false;
+ while( !converged ) {
+ //get first matching min/max
+ Hop first = hi.getInput().stream()
+ .filter(h -> HopRewriteUtils.isBinary(h, bop) || HopRewriteUtils.isNary(h, nop))
+ .findFirst().orElse(null);
+
+ //replace current op with new nary min/max
+ final Hop lhi = hi;
+ if( first != null && first.getParent().size()==1
+ && first.getInput().stream().allMatch(c -> c.getDataType()==DataType.SCALAR
+ || HopRewriteUtils.isEqualSize(lhi, c))) {
+ //construct new list of inputs (in original order)
+ ArrayList<Hop> linputs = new ArrayList<>();
+ for(Hop in : hi.getInput())
+ if( in == first )
+ linputs.addAll(first.getInput());
+ else
+ linputs.add(in);
+ Hop hnew = HopRewriteUtils.createNary(nop, linputs.toArray(new Hop[0]));
+ //clear dangling references
+ HopRewriteUtils.removeAllChildReferences(hi);
+ HopRewriteUtils.removeAllChildReferences(first);
+ //rewire all parents (avoid anomalies with refs to hi)
+ List<Hop> parents = new ArrayList<>(hi.getParent());
+ for( Hop p : parents )
+ HopRewriteUtils.replaceChildReference(p, hi, hnew);
+ hi = hnew;
+ LOG.debug("Applied foldMultipleMinMaxOperations (line "+hi.getBeginLine()+").");
+ }
+ else {
+ converged = true;
+ }
+ }
+ }
+
+ return hi;
+ }
}
http://git-wip-us.apache.org/repos/asf/systemml/blob/8d320791/src/test/java/org/apache/sysml/test/integration/functions/misc/RewriteFoldMinMaxTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/sysml/test/integration/functions/misc/RewriteFoldMinMaxTest.java b/src/test/java/org/apache/sysml/test/integration/functions/misc/RewriteFoldMinMaxTest.java
new file mode 100644
index 0000000..65c2a3e
--- /dev/null
+++ b/src/test/java/org/apache/sysml/test/integration/functions/misc/RewriteFoldMinMaxTest.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sysml.test.integration.functions.misc;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.sysml.api.DMLScript;
+import org.apache.sysml.api.DMLScript.RUNTIME_PLATFORM;
+import org.apache.sysml.hops.OptimizerUtils;
+import org.apache.sysml.lops.LopProperties.ExecType;
+import org.apache.sysml.runtime.matrix.data.MatrixValue.CellIndex;
+import org.apache.sysml.test.integration.AutomatedTestBase;
+import org.apache.sysml.test.integration.TestConfiguration;
+import org.apache.sysml.test.utils.TestUtils;
+import org.apache.sysml.utils.Statistics;
+
+public class RewriteFoldMinMaxTest extends AutomatedTestBase
+{
+ private static final String TEST_NAME1 = "RewriteFoldMin";
+ private static final String TEST_NAME2 = "RewriteFoldMax";
+
+ private static final String TEST_DIR = "functions/misc/";
+ private static final String TEST_CLASS_DIR = TEST_DIR + RewriteFoldMinMaxTest.class.getSimpleName() + "/";
+
+ private static final int rows = 1932;
+ private static final int cols = 14;
+
+ @Override
+ public void setUp() {
+ TestUtils.clearAssertionInformation();
+ addTestConfiguration( TEST_NAME1, new TestConfiguration(TEST_CLASS_DIR, TEST_NAME1, new String[] { "R" }) );
+ addTestConfiguration( TEST_NAME2, new TestConfiguration(TEST_CLASS_DIR, TEST_NAME2, new String[] { "R" }) );
+ }
+
+ @Test
+ public void testRewriteFoldMinNoRewrite() {
+ testRewriteFoldMinMax( TEST_NAME1, false, ExecType.CP );
+ }
+
+ @Test
+ public void testRewriteFoldMinRewrite() {
+ testRewriteFoldMinMax( TEST_NAME1, true, ExecType.CP );
+ }
+
+ @Test
+ public void testRewriteFoldMaxNoRewrite() {
+ testRewriteFoldMinMax( TEST_NAME2, false, ExecType.CP );
+ }
+
+ @Test
+ public void testRewriteFoldMaxRewrite() {
+ testRewriteFoldMinMax( TEST_NAME2, true, ExecType.CP );
+ }
+
+ private void testRewriteFoldMinMax( String testname, boolean rewrites, ExecType et )
+ {
+ RUNTIME_PLATFORM platformOld = rtplatform;
+ switch( et ){
+ case MR: rtplatform = RUNTIME_PLATFORM.HADOOP; break;
+ case SPARK: rtplatform = RUNTIME_PLATFORM.SPARK; break;
+ default: rtplatform = RUNTIME_PLATFORM.HYBRID_SPARK; break;
+ }
+
+ boolean sparkConfigOld = DMLScript.USE_LOCAL_SPARK_CONFIG;
+ if( rtplatform == RUNTIME_PLATFORM.SPARK || rtplatform == RUNTIME_PLATFORM.HYBRID_SPARK )
+ DMLScript.USE_LOCAL_SPARK_CONFIG = true;
+
+ boolean oldFlag = OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION;
+
+ try {
+ TestConfiguration config = getTestConfiguration(testname);
+ loadTestConfiguration(config);
+
+ String HOME = SCRIPT_DIR + TEST_DIR;
+ fullDMLScriptName = HOME + testname + ".dml";
+ programArgs = new String[]{ "-stats", "-args", String.valueOf(rows),
+ String.valueOf(cols), output("R") };
+ OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION = rewrites;
+
+ //run performance tests
+ runTest(true, false, null, -1);
+
+ //compare matrices
+ Double ret = readDMLMatrixFromHDFS("R").get(new CellIndex(1,1));
+ Assert.assertEquals("Wrong result", new Double(5*rows*cols), ret);
+
+ //check for applied rewrites
+ if( rewrites ) {
+ Assert.assertTrue(!heavyHittersContainsString("min") && !heavyHittersContainsString("max")
+ && (!testname.equals(TEST_NAME1) || Statistics.getCPHeavyHitterCount("nmin") == 1)
+ && (!testname.equals(TEST_NAME2) || Statistics.getCPHeavyHitterCount("nmax") == 1));
+ }
+ }
+ finally {
+ OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION = oldFlag;
+ DMLScript.USE_LOCAL_SPARK_CONFIG = sparkConfigOld;
+ rtplatform = platformOld;
+ }
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/systemml/blob/8d320791/src/test/scripts/functions/misc/RewriteFoldMax.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/RewriteFoldMax.dml b/src/test/scripts/functions/misc/RewriteFoldMax.dml
new file mode 100644
index 0000000..c5117c8
--- /dev/null
+++ b/src/test/scripts/functions/misc/RewriteFoldMax.dml
@@ -0,0 +1,28 @@
+#-------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#-------------------------------------------------------------
+
+X = matrix(1, $1, $2)
+while(FALSE){}
+Y = max(X-7,max(max(X-5,-7),5))
+while(FALSE){}
+R = as.matrix(sum(Y))
+
+write(R, $3);
http://git-wip-us.apache.org/repos/asf/systemml/blob/8d320791/src/test/scripts/functions/misc/RewriteFoldMin.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/RewriteFoldMin.dml b/src/test/scripts/functions/misc/RewriteFoldMin.dml
new file mode 100644
index 0000000..7919d9b
--- /dev/null
+++ b/src/test/scripts/functions/misc/RewriteFoldMin.dml
@@ -0,0 +1,28 @@
+#-------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#-------------------------------------------------------------
+
+X = matrix(1, $1, $2)
+while(FALSE){}
+Y = min(X+7,min(min(X+5,7),5))
+while(FALSE){}
+R = as.matrix(sum(Y))
+
+write(R, $3);
http://git-wip-us.apache.org/repos/asf/systemml/blob/8d320791/src/test_suites/java/org/apache/sysml/test/integration/functions/misc/ZPackageSuite.java
----------------------------------------------------------------------
diff --git a/src/test_suites/java/org/apache/sysml/test/integration/functions/misc/ZPackageSuite.java b/src/test_suites/java/org/apache/sysml/test/integration/functions/misc/ZPackageSuite.java
index e2c7bf1..75e9970 100644
--- a/src/test_suites/java/org/apache/sysml/test/integration/functions/misc/ZPackageSuite.java
+++ b/src/test_suites/java/org/apache/sysml/test/integration/functions/misc/ZPackageSuite.java
@@ -61,6 +61,7 @@ import org.junit.runners.Suite;
RewriteCTableToRExpandTest.class,
RewriteElementwiseMultChainOptimizationTest.class,
RewriteEliminateAggregatesTest.class,
+ RewriteFoldMinMaxTest.class,
RewriteFoldRCBindTest.class,
RewriteFuseBinaryOpChainTest.class,
RewriteFusedRandTest.class,
[2/2] systemml git commit: [SYSTEMML-2273] Codegen support for nary
min/max in cell/row templates
Posted by mb...@apache.org.
[SYSTEMML-2273] Codegen support for nary min/max in cell/row templates
This patch adds operator fusion and code generation support for the new
nary min/max operator in cell and row templates. For both scenarios, we
map the nary operator to binary codegen operations which are anyway
fused on a cell or row level without additional overhead and thus no
need for additional template or runtime primitives.
Project: http://git-wip-us.apache.org/repos/asf/systemml/repo
Commit: http://git-wip-us.apache.org/repos/asf/systemml/commit/4d370a8a
Tree: http://git-wip-us.apache.org/repos/asf/systemml/tree/4d370a8a
Diff: http://git-wip-us.apache.org/repos/asf/systemml/diff/4d370a8a
Branch: refs/heads/master
Commit: 4d370a8a6fb73329c46f12a3b6775d0b7817dad4
Parents: 8d32079
Author: Matthias Boehm <mb...@gmail.com>
Authored: Thu Jun 7 23:37:33 2018 -0700
Committer: Matthias Boehm <mb...@gmail.com>
Committed: Thu Jun 7 23:37:33 2018 -0700
----------------------------------------------------------------------
.../hops/codegen/template/TemplateCell.java | 19 +++++++--
.../hops/codegen/template/TemplateRow.java | 43 +++++++++++++-------
.../functions/codegen/CellwiseTmplTest.java | 24 +++++++++--
.../functions/codegen/RowAggTmplTest.java | 21 +++++++++-
.../scripts/functions/codegen/cellwisetmpl23.R | 31 ++++++++++++++
.../functions/codegen/cellwisetmpl23.dml | 30 ++++++++++++++
.../scripts/functions/codegen/rowAggPattern42.R | 31 ++++++++++++++
.../functions/codegen/rowAggPattern42.dml | 30 ++++++++++++++
8 files changed, 207 insertions(+), 22 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/systemml/blob/4d370a8a/src/main/java/org/apache/sysml/hops/codegen/template/TemplateCell.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/codegen/template/TemplateCell.java b/src/main/java/org/apache/sysml/hops/codegen/template/TemplateCell.java
index 0ce35c6..0106a59 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/template/TemplateCell.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/template/TemplateCell.java
@@ -37,9 +37,11 @@ import org.apache.sysml.hops.Hop.AggOp;
import org.apache.sysml.hops.Hop.DataGenMethod;
import org.apache.sysml.hops.Hop.OpOp2;
import org.apache.sysml.hops.Hop.OpOp3;
+import org.apache.sysml.hops.Hop.OpOpN;
import org.apache.sysml.hops.Hop.ParamBuiltinOp;
import org.apache.sysml.hops.IndexingOp;
import org.apache.sysml.hops.LiteralOp;
+import org.apache.sysml.hops.NaryOp;
import org.apache.sysml.hops.ParameterizedBuiltinOp;
import org.apache.sysml.hops.TernaryOp;
import org.apache.sysml.hops.codegen.cplan.CNode;
@@ -82,7 +84,8 @@ public class TemplateCell extends TemplateBase
|| (hop instanceof IndexingOp && hop.getInput().get(0).getDim2() >= 0
&& (((IndexingOp)hop).isColLowerEqualsUpper() || hop.getDim2()==1))
|| (HopRewriteUtils.isDataGenOpWithLiteralInputs(hop, DataGenMethod.SEQ)
- && HopRewriteUtils.hasOnlyUnaryBinaryParents(hop, true));
+ && HopRewriteUtils.hasOnlyUnaryBinaryParents(hop, true))
+ || (HopRewriteUtils.isNary(hop, OpOpN.MIN, OpOpN.MAX) && hop.isMatrix());
}
@Override
@@ -93,7 +96,8 @@ public class TemplateCell extends TemplateBase
&& hop.getDim1()==1 && hop.getDim2()==1)
&& HopRewriteUtils.isTransposeOperation(hop.getInput().get(0))
|| (HopRewriteUtils.isTransposeOperation(hop)
- && hop.getDim1()==1 && hop.getDim2()>1));
+ && hop.getDim1()==1 && hop.getDim2()>1))
+ || (HopRewriteUtils.isNary(hop, OpOpN.MIN, OpOpN.MAX) && hop.isMatrix());
}
@Override
@@ -103,7 +107,8 @@ public class TemplateCell extends TemplateBase
|| (hop instanceof AggBinaryOp && hop.getInput().indexOf(input)==0
&& HopRewriteUtils.isTransposeOperation(input))))
|| (HopRewriteUtils.isDataGenOpWithLiteralInputs(input, DataGenMethod.SEQ)
- && HopRewriteUtils.hasOnlyUnaryBinaryParents(input, false));
+ && HopRewriteUtils.hasOnlyUnaryBinaryParents(input, false))
+ || (HopRewriteUtils.isNary(hop, OpOpN.MIN, OpOpN.MAX) && hop.isMatrix());
}
@Override
@@ -221,6 +226,14 @@ public class TemplateCell extends TemplateBase
out = new CNodeTernary(cdata1, cdata2, cdata3,
TernaryType.valueOf(top.getOp().name()));
}
+ else if(HopRewriteUtils.isNary(hop, OpOpN.MIN, OpOpN.MAX)) {
+ String op = ((NaryOp)hop).getOp().name();
+ CNode[] inputs = hop.getInput().stream().map(c ->
+ TemplateUtils.wrapLookupIfNecessary(tmp.get(c.getHopID()), c)).toArray(CNode[]::new);
+ out = new CNodeBinary(inputs[0], inputs[1], BinType.valueOf(op));
+ for( int i=2; i<hop.getInput().size(); i++ )
+ out = new CNodeBinary(out, inputs[i], BinType.valueOf(op));
+ }
else if( hop instanceof ParameterizedBuiltinOp ) {
CNode cdata1 = tmp.get(((ParameterizedBuiltinOp)hop).getTargetHop().getHopID());
cdata1 = TemplateUtils.wrapLookupIfNecessary(cdata1, hop.getInput().get(0));
http://git-wip-us.apache.org/repos/asf/systemml/blob/4d370a8a/src/main/java/org/apache/sysml/hops/codegen/template/TemplateRow.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/codegen/template/TemplateRow.java b/src/main/java/org/apache/sysml/hops/codegen/template/TemplateRow.java
index 737b30d..55b62ba 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/template/TemplateRow.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/template/TemplateRow.java
@@ -31,6 +31,7 @@ import org.apache.sysml.hops.DataGenOp;
import org.apache.sysml.hops.Hop;
import org.apache.sysml.hops.IndexingOp;
import org.apache.sysml.hops.LiteralOp;
+import org.apache.sysml.hops.NaryOp;
import org.apache.sysml.hops.ParameterizedBuiltinOp;
import org.apache.sysml.hops.TernaryOp;
import org.apache.sysml.hops.UnaryOp;
@@ -92,6 +93,7 @@ public class TemplateRow extends TemplateBase
|| (HopRewriteUtils.isBinary(hop, OpOp2.CBIND) && hop.getInput().get(0).isMatrix() && hop.dimsKnown())
|| HopRewriteUtils.isTernary(hop, OpOp3.PLUS_MULT, OpOp3.MINUS_MULT)
|| (HopRewriteUtils.isNary(hop, OpOpN.CBIND) && hop.getInput().get(0).isMatrix() && hop.dimsKnown())
+ || (HopRewriteUtils.isNary(hop, OpOpN.MIN, OpOpN.MAX) && hop.isMatrix())
|| (hop instanceof AggBinaryOp && hop.dimsKnown() && hop.getDim2()==1 //MV
&& hop.getInput().get(0).getDim1()>1 && hop.getInput().get(0).getDim2()>1)
|| (hop instanceof AggBinaryOp && hop.dimsKnown() && LibMatrixMult.isSkinnyRightHandSide(
@@ -117,6 +119,7 @@ public class TemplateRow extends TemplateBase
( (hop instanceof BinaryOp && isValidBinaryOperation(hop))
|| (HopRewriteUtils.isBinary(hop, OpOp2.CBIND) && hop.getInput().get(0).isMatrix() && hop.dimsKnown())
|| (HopRewriteUtils.isNary(hop, OpOpN.CBIND) && hop.getInput().get(0).isMatrix() && hop.dimsKnown())
+ || (HopRewriteUtils.isNary(hop, OpOpN.MIN, OpOpN.MAX) && hop.isMatrix())
|| ((hop instanceof UnaryOp || hop instanceof ParameterizedBuiltinOp)
&& TemplateCell.isValidOperation(hop))
|| HopRewriteUtils.isTernary(hop, OpOp3.PLUS_MULT, OpOp3.MINUS_MULT)
@@ -141,6 +144,7 @@ public class TemplateRow extends TemplateBase
&& hop.getDim1() > 1 && input.getDim1()>1)
|| (HopRewriteUtils.isBinary(hop, OpOp2.CBIND) && hop.getInput().get(0).isMatrix() && hop.dimsKnown())
|| (HopRewriteUtils.isNary(hop, OpOpN.CBIND) && hop.getInput().get(0).isMatrix() && hop.dimsKnown())
+ || (HopRewriteUtils.isNary(hop, OpOpN.MIN, OpOpN.MAX) && hop.isMatrix())
|| (HopRewriteUtils.isDataGenOpWithLiteralInputs(input, DataGenMethod.SEQ)
&& HopRewriteUtils.hasOnlyUnaryBinaryParents(input, false))
|| (hop instanceof AggBinaryOp
@@ -408,19 +412,11 @@ public class TemplateRow extends TemplateBase
&& (cdata1.getDataType().isMatrix() || cdata2.getDataType().isMatrix())))
{
if( HopRewriteUtils.isBinary(hop, SUPPORTED_VECT_BINARY) ) {
- if( TemplateUtils.isMatrix(cdata1) && (TemplateUtils.isMatrix(cdata2)
- || TemplateUtils.isRowVector(cdata2)) ) {
- String opname = "VECT_"+((BinaryOp)hop).getOp().name();
- out = new CNodeBinary(cdata1, cdata2, BinType.valueOf(opname));
- }
- else {
- String opname = "VECT_"+((BinaryOp)hop).getOp().name()+"_SCALAR";
- if( TemplateUtils.isColVector(cdata1) )
- cdata1 = new CNodeUnary(cdata1, UnaryType.LOOKUP_R);
- if( TemplateUtils.isColVector(cdata2) )
- cdata2 = new CNodeUnary(cdata2, UnaryType.LOOKUP_R);
- out = new CNodeBinary(cdata1, cdata2, BinType.valueOf(opname));
- }
+ if( TemplateUtils.isColVector(cdata1) )
+ cdata1 = new CNodeUnary(cdata1, UnaryType.LOOKUP_R);
+ if( TemplateUtils.isColVector(cdata2) )
+ cdata2 = new CNodeUnary(cdata2, UnaryType.LOOKUP_R);
+ out = getVectorBinary(cdata1, cdata2, ((BinaryOp)hop).getOp().name());
if( cdata1 instanceof CNodeData && !inHops2.containsKey("X")
&& !(cdata1.getDataType()==DataType.SCALAR) ) {
inHops2.put("X", hop.getInput().get(0));
@@ -463,7 +459,7 @@ public class TemplateRow extends TemplateBase
TernaryType.valueOf(top.getOp().name()));
}
}
- else if(HopRewriteUtils.isNary(hop, OpOpN.CBIND)) {
+ else if( hop instanceof NaryOp ) {
CNode[] inputs = new CNode[hop.getInput().size()];
for( int i=0; i<hop.getInput().size(); i++ ) {
Hop c = hop.getInput().get(i);
@@ -474,7 +470,14 @@ public class TemplateRow extends TemplateBase
if( i==0 && cdata instanceof CNodeData && !inHops2.containsKey("X") )
inHops2.put("X", c);
}
- out = new CNodeNary(inputs, NaryType.VECT_CBIND);
+ if( HopRewriteUtils.isNary(hop, OpOpN.CBIND) ) {
+ out = new CNodeNary(inputs, NaryType.VECT_CBIND);
+ }
+ else if( HopRewriteUtils.isNary(hop, OpOpN.MIN, OpOpN.MAX) ) {
+ out = getVectorBinary(inputs[0], inputs[1], ((NaryOp)hop).getOp().name());
+ for( int i=2; i<hop.getInput().size(); i++ )
+ out = getVectorBinary(out, inputs[i], ((NaryOp)hop).getOp().name());
+ }
}
else if( hop instanceof ParameterizedBuiltinOp ) {
CNode cdata1 = tmp.get(((ParameterizedBuiltinOp)hop).getTargetHop().getHopID());
@@ -505,6 +508,16 @@ public class TemplateRow extends TemplateBase
tmp.put(hop.getHopID(), out);
}
+ private CNodeBinary getVectorBinary(CNode cdata1, CNode cdata2, String name) {
+ if( TemplateUtils.isMatrix(cdata1) && (TemplateUtils.isMatrix(cdata2)
+ || TemplateUtils.isRowVector(cdata2)) ) {
+ return new CNodeBinary(cdata1, cdata2, BinType.valueOf("VECT_"+name));
+ }
+ else {
+ return new CNodeBinary(cdata1, cdata2, BinType.valueOf("VECT_"+name+"_SCALAR"));
+ }
+ }
+
/**
* Comparator to order input hops of the row aggregate template. We try
* to order matrices-vectors-scalars via sorting by number of cells but
http://git-wip-us.apache.org/repos/asf/systemml/blob/4d370a8a/src/test/java/org/apache/sysml/test/integration/functions/codegen/CellwiseTmplTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/sysml/test/integration/functions/codegen/CellwiseTmplTest.java b/src/test/java/org/apache/sysml/test/integration/functions/codegen/CellwiseTmplTest.java
index 76469de..cfcabde 100644
--- a/src/test/java/org/apache/sysml/test/integration/functions/codegen/CellwiseTmplTest.java
+++ b/src/test/java/org/apache/sysml/test/integration/functions/codegen/CellwiseTmplTest.java
@@ -58,6 +58,7 @@ public class CellwiseTmplTest extends AutomatedTestBase
private static final String TEST_NAME20 = TEST_NAME+20; //bitwAnd() operation
private static final String TEST_NAME21 = TEST_NAME+21; //relu operation, (X>0)*dout
private static final String TEST_NAME22 = TEST_NAME+22; //sum(X * seq(1,N) + t(seq(M,1)))
+ private static final String TEST_NAME23 = TEST_NAME+23; //sum(min(X,Y,Z))
private static final String TEST_DIR = "functions/codegen/";
private static final String TEST_CLASS_DIR = TEST_DIR + CellwiseTmplTest.class.getSimpleName() + "/";
@@ -70,7 +71,7 @@ public class CellwiseTmplTest extends AutomatedTestBase
@Override
public void setUp() {
TestUtils.clearAssertionInformation();
- for( int i=1; i<=22; i++ ) {
+ for( int i=1; i<=23; i++ ) {
addTestConfiguration( TEST_NAME+i, new TestConfiguration(
TEST_CLASS_DIR, TEST_NAME+i, new String[] {String.valueOf(i)}) );
}
@@ -382,6 +383,21 @@ public class CellwiseTmplTest extends AutomatedTestBase
public void testCodegenCellwiseRewrite22_sp() {
testCodegenIntegration( TEST_NAME22, true, ExecType.SPARK );
}
+
+ @Test
+ public void testCodegenCellwiseRewrite23() {
+ testCodegenIntegration( TEST_NAME23, true, ExecType.CP );
+ }
+
+ @Test
+ public void testCodegenCellwise23() {
+ testCodegenIntegration( TEST_NAME23, false, ExecType.CP );
+ }
+
+ @Test
+ public void testCodegenCellwiseRewrite23_sp() {
+ testCodegenIntegration( TEST_NAME23, true, ExecType.SPARK );
+ }
private void testCodegenIntegration( String testname, boolean rewrites, ExecType instType )
{
@@ -409,7 +425,7 @@ public class CellwiseTmplTest extends AutomatedTestBase
String HOME = SCRIPT_DIR + TEST_DIR;
fullDMLScriptName = HOME + testname + ".dml";
- programArgs = new String[]{"-explain", "hops", "-stats", "-args", output("S") };
+ programArgs = new String[]{"-explain", "-stats", "-args", output("S") };
fullRScriptName = HOME + testname + ".R";
rCmd = getRCmd(inputDir(), expectedDir());
@@ -420,7 +436,7 @@ public class CellwiseTmplTest extends AutomatedTestBase
runRScript(true);
if(testname.equals(TEST_NAME6) || testname.equals(TEST_NAME7)
- || testname.equals(TEST_NAME9) || testname.equals(TEST_NAME10) ) {
+ || testname.equals(TEST_NAME9) || testname.equals(TEST_NAME10)) {
//compare scalars
HashMap<CellIndex, Double> dmlfile = readDMLScalarFromHDFS("S");
HashMap<CellIndex, Double> rfile = readRScalarFromFS("S");
@@ -451,6 +467,8 @@ public class CellwiseTmplTest extends AutomatedTestBase
Assert.assertTrue(!heavyHittersContainsSubString("xor"));
else if( testname.equals(TEST_NAME22) )
Assert.assertTrue(!heavyHittersContainsSubString("seq"));
+ else if( testname.equals(TEST_NAME23) )
+ Assert.assertTrue(!heavyHittersContainsSubString("min","nmin"));
}
finally {
rtplatform = platformOld;
http://git-wip-us.apache.org/repos/asf/systemml/blob/4d370a8a/src/test/java/org/apache/sysml/test/integration/functions/codegen/RowAggTmplTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/sysml/test/integration/functions/codegen/RowAggTmplTest.java b/src/test/java/org/apache/sysml/test/integration/functions/codegen/RowAggTmplTest.java
index e07c543..203e9b1 100644
--- a/src/test/java/org/apache/sysml/test/integration/functions/codegen/RowAggTmplTest.java
+++ b/src/test/java/org/apache/sysml/test/integration/functions/codegen/RowAggTmplTest.java
@@ -78,6 +78,7 @@ public class RowAggTmplTest extends AutomatedTestBase
private static final String TEST_NAME39 = TEST_NAME+"39"; //BitwAnd operation
private static final String TEST_NAME40 = TEST_NAME+"40"; //relu operation -> (X>0)* dout
private static final String TEST_NAME41 = TEST_NAME+"41"; //X*rowSums(X/seq(1,N)+t(seq(M,1)))
+ private static final String TEST_NAME42 = TEST_NAME+"42"; //X/rowSums(min(X, Y, Z))
private static final String TEST_DIR = "functions/codegen/";
private static final String TEST_CLASS_DIR = TEST_DIR + RowAggTmplTest.class.getSimpleName() + "/";
@@ -89,7 +90,7 @@ public class RowAggTmplTest extends AutomatedTestBase
@Override
public void setUp() {
TestUtils.clearAssertionInformation();
- for(int i=1; i<=41; i++)
+ for(int i=1; i<=42; i++)
addTestConfiguration( TEST_NAME+i, new TestConfiguration(TEST_CLASS_DIR, TEST_NAME+i, new String[] { String.valueOf(i) }) );
}
@@ -707,6 +708,21 @@ public class RowAggTmplTest extends AutomatedTestBase
public void testCodegenRowAgg41SP() {
testCodegenIntegration( TEST_NAME41, false, ExecType.SPARK );
}
+
+ @Test
+ public void testCodegenRowAggRewrite42CP() {
+ testCodegenIntegration( TEST_NAME42, true, ExecType.CP );
+ }
+
+ @Test
+ public void testCodegenRowAgg42CP() {
+ testCodegenIntegration( TEST_NAME42, false, ExecType.CP );
+ }
+
+ @Test
+ public void testCodegenRowAgg42SP() {
+ testCodegenIntegration( TEST_NAME42, false, ExecType.SPARK );
+ }
private void testCodegenIntegration( String testname, boolean rewrites, ExecType instType )
{
@@ -766,6 +782,9 @@ public class RowAggTmplTest extends AutomatedTestBase
Assert.assertTrue(!heavyHittersContainsSubString("xor"));
if( testname.equals(TEST_NAME41) )
Assert.assertTrue(!heavyHittersContainsSubString("seq"));
+ if( testname.equals(TEST_NAME42) )
+ Assert.assertTrue(!heavyHittersContainsSubString("min","nmin")
+ && !heavyHittersContainsSubString("spoof", 2));
}
finally {
rtplatform = platformOld;
http://git-wip-us.apache.org/repos/asf/systemml/blob/4d370a8a/src/test/scripts/functions/codegen/cellwisetmpl23.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/codegen/cellwisetmpl23.R b/src/test/scripts/functions/codegen/cellwisetmpl23.R
new file mode 100644
index 0000000..9dffe0a
--- /dev/null
+++ b/src/test/scripts/functions/codegen/cellwisetmpl23.R
@@ -0,0 +1,31 @@
+#-------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#-------------------------------------------------------------
+
+args<-commandArgs(TRUE)
+options(digits=22)
+library("Matrix")
+
+X = matrix(6, 500, 2);
+Y = matrix(7, 500, 2);
+Z = matrix(8, 500, 2);
+R = as.matrix(sum(pmin(X,Y,Z)));
+
+writeMM(as(R,"CsparseMatrix"), paste(args[2], "S", sep=""));
http://git-wip-us.apache.org/repos/asf/systemml/blob/4d370a8a/src/test/scripts/functions/codegen/cellwisetmpl23.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/codegen/cellwisetmpl23.dml b/src/test/scripts/functions/codegen/cellwisetmpl23.dml
new file mode 100644
index 0000000..8e53d27
--- /dev/null
+++ b/src/test/scripts/functions/codegen/cellwisetmpl23.dml
@@ -0,0 +1,30 @@
+#-------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#-------------------------------------------------------------
+
+X = matrix(6, 500, 2);
+Y = matrix(7, 500, 2);
+Z = matrix(8, 500, 2);
+
+while(FALSE){}
+
+R = as.matrix(sum(min(X,Y,Z)));
+
+write(R, $1)
http://git-wip-us.apache.org/repos/asf/systemml/blob/4d370a8a/src/test/scripts/functions/codegen/rowAggPattern42.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/codegen/rowAggPattern42.R b/src/test/scripts/functions/codegen/rowAggPattern42.R
new file mode 100644
index 0000000..2214a46
--- /dev/null
+++ b/src/test/scripts/functions/codegen/rowAggPattern42.R
@@ -0,0 +1,31 @@
+#-------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#-------------------------------------------------------------
+
+args<-commandArgs(TRUE)
+options(digits=22)
+library("Matrix")
+
+X = matrix(6, 500, 2);
+Y = matrix(7, 500, 2);
+Z = matrix(8, 500, 2);
+R = X / (rowSums(pmin(X, Y, Z)) %*% matrix(1,1,2));
+
+writeMM(as(R,"CsparseMatrix"), paste(args[2], "S", sep=""));
http://git-wip-us.apache.org/repos/asf/systemml/blob/4d370a8a/src/test/scripts/functions/codegen/rowAggPattern42.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/codegen/rowAggPattern42.dml b/src/test/scripts/functions/codegen/rowAggPattern42.dml
new file mode 100644
index 0000000..78647c7
--- /dev/null
+++ b/src/test/scripts/functions/codegen/rowAggPattern42.dml
@@ -0,0 +1,30 @@
+#-------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#-------------------------------------------------------------
+
+X = matrix(6, 500, 2);
+Y = matrix(7, 500, 2);
+Z = matrix(8, 500, 2);
+
+while(FALSE){}
+
+R = X / rowSums(min(X, Y, Z));
+
+write(R, $1)