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 2017/06/20 19:59:45 UTC

systemml git commit: [SYSTEMML-1725] Extended codegen row-wise template (full rc aggregates)

Repository: systemml
Updated Branches:
  refs/heads/master 244f8049d -> d71a7d359


[SYSTEMML-1725] Extended codegen row-wise template (full rc aggregates)

This patch extends the code generator row-wise template by support for
full row/column aggregations (in addition to the types no_agg, row_agg,
col_agg). The motivation for this are scenarios where we currently
compile a sequence of row-wise and cell-wise templates, because the
patterns contain both intermediate row aggregates and a final full
aggregation. 

For example, on Mlogreg over an 100Mx10 input, this patch improved
end-to-end performance with codegen from 248s with (w/ 59/29/1
bufferpool writes) to 193s (w/ 45/15/1 bufferpool writes). In
comparison, without codegen but existing fused operators, the end-to-end
performance was 512s (w/ 234/30/1 writes).

Project: http://git-wip-us.apache.org/repos/asf/systemml/repo
Commit: http://git-wip-us.apache.org/repos/asf/systemml/commit/d71a7d35
Tree: http://git-wip-us.apache.org/repos/asf/systemml/tree/d71a7d35
Diff: http://git-wip-us.apache.org/repos/asf/systemml/diff/d71a7d35

Branch: refs/heads/master
Commit: d71a7d359ba1d776feff8447e02646a2623a41af
Parents: 244f804
Author: Matthias Boehm <mb...@gmail.com>
Authored: Tue Jun 20 12:59:47 2017 -0700
Committer: Matthias Boehm <mb...@gmail.com>
Committed: Tue Jun 20 13:00:00 2017 -0700

----------------------------------------------------------------------
 .../sysml/hops/codegen/cplan/CNodeRow.java      | 10 ++++---
 .../hops/codegen/template/TemplateRow.java      | 12 ++++++--
 .../hops/codegen/template/TemplateUtils.java    |  3 ++
 .../sysml/hops/rewrite/HopRewriteUtils.java     |  5 +---
 .../sysml/runtime/codegen/SpoofRowwise.java     | 20 +++++++++++--
 .../instructions/spark/SpoofSPInstruction.java  | 16 ++++++----
 .../functions/codegen/RowAggTmplTest.java       | 18 +++++++++++-
 .../scripts/functions/codegen/rowAggPattern21.R | 31 ++++++++++++++++++++
 .../functions/codegen/rowAggPattern21.dml       | 26 ++++++++++++++++
 9 files changed, 122 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/systemml/blob/d71a7d35/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeRow.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeRow.java b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeRow.java
index b2b16f2..546bf60 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeRow.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeRow.java
@@ -48,8 +48,9 @@ public class CNodeRow extends CNodeTpl
 			+ "  }\n"			
 			+ "}\n";
 
-	private static final String TEMPLATE_ROWAGG_OUT = "    c[rowIndex] = %IN%;\n";
-	private static final String TEMPLATE_NOAGG_OUT = "    LibSpoofPrimitives.vectWrite(%IN%, c, rowIndex*len, len);\n";
+	private static final String TEMPLATE_ROWAGG_OUT  = "    c[rowIndex] = %IN%;\n";
+	private static final String TEMPLATE_FULLAGG_OUT = "    c[0] += %IN%;\n";
+	private static final String TEMPLATE_NOAGG_OUT   = "    LibSpoofPrimitives.vectWrite(%IN%, c, rowIndex*len, len);\n";
 	
 	public CNodeRow(ArrayList<CNode> inputs, CNode output ) {
 		super(inputs, output);
@@ -114,8 +115,8 @@ public class CNodeRow extends CNodeTpl
 	
 	private String getOutputStatement(String varName) {
 		if( !_type.isColumnAgg() ) {
-			String tmp = (_type==RowType.NO_AGG) ?
-				TEMPLATE_NOAGG_OUT : TEMPLATE_ROWAGG_OUT;
+			String tmp = (_type==RowType.NO_AGG) ? TEMPLATE_NOAGG_OUT : 
+				(_type==RowType.FULL_AGG) ? TEMPLATE_FULLAGG_OUT : TEMPLATE_ROWAGG_OUT;
 			return tmp.replace("%IN%", varName);
 		}
 		return "";
@@ -131,6 +132,7 @@ public class CNodeRow extends CNodeTpl
 	public SpoofOutputDimsType getOutputDimType() {
 		switch( _type ) {
 			case NO_AGG: return SpoofOutputDimsType.INPUT_DIMS;
+			case FULL_AGG: return SpoofOutputDimsType.SCALAR;
 			case ROW_AGG: return TemplateUtils.isUnary(_output, UnaryType.CBIND0) ?
 				SpoofOutputDimsType.ROW_DIMS2 : SpoofOutputDimsType.ROW_DIMS;
 			case COL_AGG: return SpoofOutputDimsType.COLUMN_DIMS_COLS; //row vector

http://git-wip-us.apache.org/repos/asf/systemml/blob/d71a7d35/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 ca10569..71091cf 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
@@ -96,6 +96,8 @@ public class TemplateRow extends TemplateBase
 					&& TemplateCell.isValidOperation(hop))		
 			|| (hop instanceof AggUnaryOp && ((AggUnaryOp)hop).getDirection()!=Direction.RowCol
 				&& HopRewriteUtils.isAggUnaryOp(hop, SUPPORTED_ROW_AGG))
+			|| (hop instanceof AggUnaryOp && ((AggUnaryOp)hop).getDirection() == Direction.RowCol 
+				&& ((AggUnaryOp)hop).getOp() == AggOp.SUM )
 			|| (hop instanceof AggBinaryOp && hop.getDim1()>1 && hop.getDim2()==1
 				&& HopRewriteUtils.isTransposeOperation(hop.getInput().get(0))));
 	}
@@ -113,8 +115,8 @@ public class TemplateRow extends TemplateBase
 
 	@Override
 	public CloseType close(Hop hop) {
-		//close on column aggregate (e.g., colSums, t(X)%*%y)
-		if(    (hop instanceof AggUnaryOp && ((AggUnaryOp)hop).getDirection()==Direction.Col)
+		//close on column or full aggregate (e.g., colSums, t(X)%*%y)
+		if(    (hop instanceof AggUnaryOp && ((AggUnaryOp)hop).getDirection()!=Direction.Row)
 			|| (hop instanceof AggBinaryOp && HopRewriteUtils.isTransposeOperation(hop.getInput().get(0)))
 			|| HopRewriteUtils.isBinary(hop, OpOp2.CBIND) )
 			return CloseType.CLOSED_VALID;
@@ -188,7 +190,7 @@ public class TemplateRow extends TemplateBase
 						inHops2.put("X", hop.getInput().get(0));
 				}
 			}
-			else  if (((AggUnaryOp)hop).getDirection() == Direction.Col && ((AggUnaryOp)hop).getOp() == AggOp.SUM ) {
+			else if (((AggUnaryOp)hop).getDirection() == Direction.Col && ((AggUnaryOp)hop).getOp() == AggOp.SUM ) {
 				//vector add without temporary copy
 				if( cdata1 instanceof CNodeBinary && ((CNodeBinary)cdata1).getType().isVectorScalarPrimitive() )
 					out = new CNodeBinary(cdata1.getInput().get(0), cdata1.getInput().get(1), 
@@ -196,6 +198,10 @@ public class TemplateRow extends TemplateBase
 				else	
 					out = cdata1;
 			}
+			else if( ((AggUnaryOp)hop).getDirection() == Direction.RowCol && ((AggUnaryOp)hop).getOp() == AggOp.SUM ) {
+				out = (cdata1.getDataType().isMatrix()) ?
+					new CNodeUnary(cdata1, UnaryType.ROW_SUMS) : cdata1;
+			}
 		}
 		else if(hop instanceof AggBinaryOp)
 		{

http://git-wip-us.apache.org/repos/asf/systemml/blob/d71a7d35/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 fbaaab6..6111e9d 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
@@ -250,6 +250,9 @@ public class TemplateUtils
 			&& !(output instanceof AggBinaryOp && HopRewriteUtils
 				.isTransposeOfItself(output.getInput().get(0),input)))
 			return RowType.ROW_AGG;
+		else if( output instanceof AggUnaryOp 
+			&& ((AggUnaryOp)output).getDirection()==Direction.RowCol )
+			return RowType.FULL_AGG;
 		else if( output.getDim1()==input.getDim2() && output.getDim2()==1 )
 			return RowType.COL_AGG_T;
 		else

http://git-wip-us.apache.org/repos/asf/systemml/blob/d71a7d35/src/main/java/org/apache/sysml/hops/rewrite/HopRewriteUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/rewrite/HopRewriteUtils.java b/src/main/java/org/apache/sysml/hops/rewrite/HopRewriteUtils.java
index b98901a..582809e 100644
--- a/src/main/java/org/apache/sysml/hops/rewrite/HopRewriteUtils.java
+++ b/src/main/java/org/apache/sysml/hops/rewrite/HopRewriteUtils.java
@@ -854,10 +854,7 @@ public class HopRewriteUtils
 		if( !(hop instanceof AggUnaryOp) )
 			return false;
 		AggOp hopOp = ((AggUnaryOp)hop).getOp();
-		for( AggOp opi : op ) 
-			if( hopOp == opi )
-				return true;
-		return false; 
+		return ArrayUtils.contains(op, hopOp);
 	}
 	
 	public static boolean isSum(Hop hop) {

http://git-wip-us.apache.org/repos/asf/systemml/blob/d71a7d35/src/main/java/org/apache/sysml/runtime/codegen/SpoofRowwise.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/codegen/SpoofRowwise.java b/src/main/java/org/apache/sysml/runtime/codegen/SpoofRowwise.java
index 529b838..104a1bf 100644
--- a/src/main/java/org/apache/sysml/runtime/codegen/SpoofRowwise.java
+++ b/src/main/java/org/apache/sysml/runtime/codegen/SpoofRowwise.java
@@ -29,6 +29,7 @@ import java.util.concurrent.Future;
 
 import org.apache.sysml.runtime.DMLRuntimeException;
 import org.apache.sysml.runtime.compress.CompressedMatrixBlock;
+import org.apache.sysml.runtime.instructions.cp.DoubleObject;
 import org.apache.sysml.runtime.instructions.cp.ScalarObject;
 import org.apache.sysml.runtime.matrix.data.LibMatrixMult;
 import org.apache.sysml.runtime.matrix.data.MatrixBlock;
@@ -45,6 +46,7 @@ public abstract class SpoofRowwise extends SpoofOperator
 	
 	public enum RowType {
 		NO_AGG,    //no aggregation
+		FULL_AGG,  //full row/col aggregation
 		ROW_AGG,   //row aggregation (e.g., rowSums() or X %*% v)
 		COL_AGG,   //col aggregation (e.g., colSums() or t(y) %*% X)
 		COL_AGG_T; //transposed col aggregation (e.g., t(X) %*% y)
@@ -82,6 +84,18 @@ public abstract class SpoofRowwise extends SpoofOperator
 	}
 	
 	@Override
+	public ScalarObject execute(ArrayList<MatrixBlock> inputs, ArrayList<ScalarObject> scalarObjects, int k) 
+		throws DMLRuntimeException 
+	{
+		MatrixBlock out = new MatrixBlock(1, 1, false);
+		if( k > 1 )
+			execute(inputs, scalarObjects, out, k);
+		else
+			execute(inputs, scalarObjects, out);
+		return new DoubleObject(out.quickGetValue(0, 0));
+	}
+	
+	@Override
 	public void execute(ArrayList<MatrixBlock> inputs, ArrayList<ScalarObject> scalarObjects, MatrixBlock out)	
 		throws DMLRuntimeException 
 	{
@@ -155,15 +169,16 @@ public abstract class SpoofRowwise extends SpoofOperator
 		int blklen = (int)(Math.ceil((double)m/nk));
 		try
 		{
-			if( _type.isColumnAgg() ) {
+			if( _type.isColumnAgg() || _type == RowType.FULL_AGG ) {
 				//execute tasks
 				ArrayList<ParColAggTask> tasks = new ArrayList<ParColAggTask>();
 				for( int i=0; i<nk & i*blklen<m; i++ )
 					tasks.add(new ParColAggTask(inputs.get(0), b, scalars, n, i*blklen, Math.min((i+1)*blklen, m)));
 				List<Future<double[]>> taskret = pool.invokeAll(tasks);	
 				//aggregate partial results
+				int len = _type.isColumnAgg() ? n : 1;
 				for( Future<double[]> task : taskret )
-					LibMatrixMult.vectAdd(task.get(), out.getDenseBlock(), 0, 0, n);
+					LibMatrixMult.vectAdd(task.get(), out.getDenseBlock(), 0, 0, len);
 				out.recomputeNonZeros();
 			}
 			else {
@@ -190,6 +205,7 @@ public abstract class SpoofRowwise extends SpoofOperator
 	private void allocateOutputMatrix(int m, int n, MatrixBlock out) {
 		switch( _type ) {
 			case NO_AGG: out.reset(m, n, false); break;
+			case FULL_AGG: out.reset(1, 1, false); break;
 			case ROW_AGG: out.reset(m, 1+(_cbind0?1:0), false); break;
 			case COL_AGG: out.reset(1, n, false); break;
 			case COL_AGG_T: out.reset(n, 1, false); break;

http://git-wip-us.apache.org/repos/asf/systemml/blob/d71a7d35/src/main/java/org/apache/sysml/runtime/instructions/spark/SpoofSPInstruction.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/instructions/spark/SpoofSPInstruction.java b/src/main/java/org/apache/sysml/runtime/instructions/spark/SpoofSPInstruction.java
index f11b3d0..622944d 100644
--- a/src/main/java/org/apache/sysml/runtime/instructions/spark/SpoofSPInstruction.java
+++ b/src/main/java/org/apache/sysml/runtime/instructions/spark/SpoofSPInstruction.java
@@ -200,11 +200,16 @@ public class SpoofSPInstruction extends SPInstruction
 		else if( _class.getSuperclass() == SpoofRowwise.class ) { //row aggregate operator
 			SpoofRowwise op = (SpoofRowwise) CodegenUtils.createInstance(_class); 	
 			RowwiseFunction fmmc = new RowwiseFunction(_class.getName(), _classBytes, bcMatrices, scalars, (int)mcIn.getCols());
-			out = in.mapPartitionsToPair(fmmc, op.getRowType()==RowType.ROW_AGG);
+			out = in.mapPartitionsToPair(fmmc, op.getRowType()==RowType.ROW_AGG
+					|| op.getRowType() == RowType.NO_AGG);
 			
-			if( op.getRowType().isColumnAgg() ) {
-				MatrixBlock tmpMB = RDDAggregateUtils.sumStable(out);		
-				sec.setMatrixOutput(_out.getName(), tmpMB);
+			if( op.getRowType().isColumnAgg() || op.getRowType()==RowType.FULL_AGG ) {
+				MatrixBlock tmpMB = RDDAggregateUtils.sumStable(out);
+				if( op.getRowType().isColumnAgg() )
+					sec.setMatrixOutput(_out.getName(), tmpMB);
+				else
+					sec.setScalarOutput(_out.getName(), 
+						new DoubleObject(tmpMB.quickGetValue(0, 0)));
 			}
 			else //row-agg or no-agg 
 			{
@@ -311,7 +316,8 @@ public class SpoofSPInstruction extends SPInstruction
 			LibSpoofPrimitives.setupThreadLocalMemory(_op.getNumIntermediates(), _clen);
 			
 			ArrayList<Tuple2<MatrixIndexes,MatrixBlock>> ret = new ArrayList<Tuple2<MatrixIndexes,MatrixBlock>>();
-			boolean aggIncr = _op.getRowType().isColumnAgg(); //aggregate entire partition to avoid allocations
+			boolean aggIncr = (_op.getRowType().isColumnAgg() //aggregate entire partition
+				|| _op.getRowType() == RowType.FULL_AGG); 
 			MatrixBlock blkOut = aggIncr ? new MatrixBlock() : null;
 			
 			while( arg.hasNext() ) {

http://git-wip-us.apache.org/repos/asf/systemml/blob/d71a7d35/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 809b812..f867e18 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
@@ -56,6 +56,7 @@ public class RowAggTmplTest extends AutomatedTestBase
 	private static final String TEST_NAME18 = TEST_NAME+"18"; //MLogreg - matrix-vector cbind 0s
 	private static final String TEST_NAME19 = TEST_NAME+"19"; //MLogreg - rowwise dag
 	private static final String TEST_NAME20 = TEST_NAME+"20"; //1 / (1 - (A / rowSums(A)))
+	private static final String TEST_NAME21 = TEST_NAME+"21"; //sum(X/rowSums(X))
 	
 	private static final String TEST_DIR = "functions/codegen/";
 	private static final String TEST_CLASS_DIR = TEST_DIR + RowAggTmplTest.class.getSimpleName() + "/";
@@ -67,7 +68,7 @@ public class RowAggTmplTest extends AutomatedTestBase
 	@Override
 	public void setUp() {
 		TestUtils.clearAssertionInformation();
-		for(int i=1; i<=20; i++)
+		for(int i=1; i<=21; i++)
 			addTestConfiguration( TEST_NAME+i, new TestConfiguration(TEST_CLASS_DIR, TEST_NAME+i, new String[] { String.valueOf(i) }) );
 	}
 	
@@ -371,6 +372,21 @@ public class RowAggTmplTest extends AutomatedTestBase
 		testCodegenIntegration( TEST_NAME20, false, ExecType.SPARK );
 	}
 	
+	@Test	
+	public void testCodegenRowAggRewrite21CP() {
+		testCodegenIntegration( TEST_NAME21, true, ExecType.CP );
+	}
+	
+	@Test
+	public void testCodegenRowAgg21CP() {
+		testCodegenIntegration( TEST_NAME21, false, ExecType.CP );
+	}
+	
+	@Test
+	public void testCodegenRowAgg21SP() {
+		testCodegenIntegration( TEST_NAME21, false, ExecType.SPARK );
+	}
+	
 	private void testCodegenIntegration( String testname, boolean rewrites, ExecType instType )
 	{	
 		boolean oldFlag = OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION;

http://git-wip-us.apache.org/repos/asf/systemml/blob/d71a7d35/src/test/scripts/functions/codegen/rowAggPattern21.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/codegen/rowAggPattern21.R b/src/test/scripts/functions/codegen/rowAggPattern21.R
new file mode 100644
index 0000000..fda9934
--- /dev/null
+++ b/src/test/scripts/functions/codegen/rowAggPattern21.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")
+library("matrixStats")
+
+A = matrix(1, 1500, 7);
+  
+R = as.matrix(sum(A / rowSums(A)));
+
+writeMM(as(R, "CsparseMatrix"), paste(args[2], "S", sep="")); 

http://git-wip-us.apache.org/repos/asf/systemml/blob/d71a7d35/src/test/scripts/functions/codegen/rowAggPattern21.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/codegen/rowAggPattern21.dml b/src/test/scripts/functions/codegen/rowAggPattern21.dml
new file mode 100644
index 0000000..b671f88
--- /dev/null
+++ b/src/test/scripts/functions/codegen/rowAggPattern21.dml
@@ -0,0 +1,26 @@
+#-------------------------------------------------------------
+#
+# 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.
+#
+#-------------------------------------------------------------
+
+A = matrix(1, 1500, 7);
+
+R = as.matrix(sum(A / rowSums(A)));
+
+write(R, $1)