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 2016/01/29 18:15:28 UTC

[2/2] incubator-systemml git commit: New static simplification rewrite 'pushdown unary-aggregate transpose'

New static simplification rewrite 'pushdown unary-aggregate transpose'

This new static (size-independent) rewrite allows to push row/column
aggregates below a transpose operation. Examples are colSums(t(X)) ->
t(rowSums(X)) and rowSums(t(X)) -> t(colSums(X)), where we support the
following aggregate functions: sum, sum_sq, min, max, mean, var. The
benefits are (1) likely reduced input size to transpose, and (2)
potentially noops for vector transpose. This patch also includes the
relevant tests for a subset of aggregate functions.

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

Branch: refs/heads/master
Commit: 5956a61255ca4f0ffc1f3b1943dbb2f3fff969bc
Parents: 0a2b587
Author: Matthias Boehm <mb...@us.ibm.com>
Authored: Thu Jan 28 21:03:25 2016 -0800
Committer: Matthias Boehm <mb...@us.ibm.com>
Committed: Fri Jan 29 09:13:39 2016 -0800

----------------------------------------------------------------------
 .../RewriteAlgebraicSimplificationStatic.java   |  55 ++++++-
 .../functions/misc/RewritePushdownUaggTest.java | 157 +++++++++++++++++++
 .../functions/misc/RewritePushdownColmins.R     |  31 ++++
 .../functions/misc/RewritePushdownColmins.dml   |  26 +++
 .../functions/misc/RewritePushdownColsums.R     |  30 ++++
 .../functions/misc/RewritePushdownColsums.dml   |  26 +++
 .../functions/misc/RewritePushdownRowmins.R     |  31 ++++
 .../functions/misc/RewritePushdownRowmins.dml   |  26 +++
 .../functions/misc/RewritePushdownRowsums.R     |  30 ++++
 .../functions/misc/RewritePushdownRowsums.dml   |  26 +++
 10 files changed, 435 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/5956a612/src/main/java/org/apache/sysml/hops/rewrite/RewriteAlgebraicSimplificationStatic.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/rewrite/RewriteAlgebraicSimplificationStatic.java b/src/main/java/org/apache/sysml/hops/rewrite/RewriteAlgebraicSimplificationStatic.java
index 3aea9f0..2368153 100644
--- a/src/main/java/org/apache/sysml/hops/rewrite/RewriteAlgebraicSimplificationStatic.java
+++ b/src/main/java/org/apache/sysml/hops/rewrite/RewriteAlgebraicSimplificationStatic.java
@@ -59,13 +59,16 @@ import org.apache.sysml.parser.Expression.ValueType;
  * 
  */
 public class RewriteAlgebraicSimplificationStatic extends HopRewriteRule
-{
-	
+{	
 	private static final Log LOG = LogFactory.getLog(RewriteAlgebraicSimplificationStatic.class.getName());
 	
+	//valid aggregation operation types for rowOp to colOp conversions and vice versa
+	private static AggOp[] LOOKUP_VALID_ROW_COL_AGGREGATE = new AggOp[]{AggOp.SUM, AggOp.SUM_SQ, AggOp.MIN, AggOp.MAX, AggOp.MEAN, AggOp.VAR};
+	
+	//valid binary operations for distributive and associate reorderings
 	private static OpOp2[] LOOKUP_VALID_DISTRIBUTIVE_BINARY = new OpOp2[]{OpOp2.PLUS, OpOp2.MINUS}; 
 	private static OpOp2[] LOOKUP_VALID_ASSOCIATIVE_BINARY = new OpOp2[]{OpOp2.PLUS, OpOp2.MULT}; 
-	
+		
 	@Override
 	public ArrayList<Hop> rewriteHopDAGs(ArrayList<Hop> roots, ProgramRewriteStatus state) 
 		throws HopsException
@@ -139,6 +142,7 @@ public class RewriteAlgebraicSimplificationStatic extends HopRewriteRule
  			hi = simplifyDistributiveBinaryOperation(hop, hi, i);//e.g., (X-Y*X) -> (1-Y)*X
  			hi = simplifyBushyBinaryOperation(hop, hi, i);       //e.g., (X*(Y*(Z%*%v))) -> (X*Y)*(Z%*%v)
  			hi = simplifyUnaryAggReorgOperation(hop, hi, i);     //e.g., sum(t(X)) -> sum(X)
+ 			hi = pushdownUnaryAggTransposeOperation(hop, hi, i); //e.g., colSums(t(X)) -> t(rowSums(X))
 			hi = simplifyUnaryPPredOperation(hop, hi, i);        //e.g., abs(ppred()) -> ppred(), others: round, ceil, floor
  			hi = simplifyTransposedAppend(hop, hi, i);           //e.g., t(cbind(t(A),t(B))) -> rbind(A,B);
  			hi = fuseBinarySubDAGToUnaryOperation(hop, hi, i);   //e.g., X*(1-X)-> sprop(X) || 1/(1+exp(-X)) -> sigmoid(X) || X*(X>0) -> selp(X)
@@ -819,6 +823,51 @@ public class RewriteAlgebraicSimplificationStatic extends HopRewriteRule
 	 * @param pos
 	 * @return
 	 */
+	private Hop pushdownUnaryAggTransposeOperation( Hop parent, Hop hi, int pos )
+	{
+		if( hi instanceof AggUnaryOp && hi.getParent().size()==1 
+			&& (((AggUnaryOp) hi).getDirection()==Direction.Row || ((AggUnaryOp) hi).getDirection()==Direction.Col)	
+			&& hi.getInput().get(0) instanceof ReorgOp && hi.getInput().get(0).getParent().size()==1
+			&& ((ReorgOp)hi.getInput().get(0)).getOp()==ReOrgOp.TRANSPOSE
+			&& HopRewriteUtils.isValidOp(((AggUnaryOp) hi).getOp(), LOOKUP_VALID_ROW_COL_AGGREGATE) )
+		{
+			AggUnaryOp uagg = (AggUnaryOp) hi;
+			
+			//get input rewire existing operators (remove inner transpose)
+			Hop input = uagg.getInput().get(0).getInput().get(0);
+			HopRewriteUtils.removeAllChildReferences(hi.getInput().get(0));
+			HopRewriteUtils.removeAllChildReferences(hi);
+			HopRewriteUtils.removeChildReferenceByPos(parent, hi, pos);
+			
+			//pattern 1: row-aggregate to col aggregate, e.g., rowSums(t(X))->t(colSums(X))
+			if( uagg.getDirection()==Direction.Row ) {
+				uagg.setDirection(Direction.Col); 
+				LOG.debug("Applied pushdownUnaryAggTransposeOperation1 (line "+hi.getBeginLine()+").");						
+			}
+			//pattern 2: col-aggregate to row aggregate, e.g., colSums(t(X))->t(rowSums(X))
+			else if( uagg.getDirection()==Direction.Col ) {
+				uagg.setDirection(Direction.Row); 
+				LOG.debug("Applied pushdownUnaryAggTransposeOperation2 (line "+hi.getBeginLine()+").");
+			}
+			
+			//create outer transpose operation and rewire operators
+			HopRewriteUtils.addChildReference(uagg, input); uagg.refreshSizeInformation();
+			Hop trans = HopRewriteUtils.createTranspose(uagg); //incl refresh size
+			HopRewriteUtils.addChildReference(parent, trans, pos); //by def, same size
+			
+			hi = trans;	
+		}
+		
+		return hi;
+	}
+	
+	/**
+	 * 
+	 * @param parent
+	 * @param hi
+	 * @param pos
+	 * @return
+	 */
 	private Hop simplifyUnaryPPredOperation( Hop parent, Hop hi, int pos )
 	{
 		if( hi instanceof UnaryOp && hi.getDataType()==DataType.MATRIX  //unaryop

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/5956a612/src/test/java/org/apache/sysml/test/integration/functions/misc/RewritePushdownUaggTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/sysml/test/integration/functions/misc/RewritePushdownUaggTest.java b/src/test/java/org/apache/sysml/test/integration/functions/misc/RewritePushdownUaggTest.java
new file mode 100644
index 0000000..348cfbb
--- /dev/null
+++ b/src/test/java/org/apache/sysml/test/integration/functions/misc/RewritePushdownUaggTest.java
@@ -0,0 +1,157 @@
+/*
+ * 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 java.util.HashMap;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.sysml.hops.OptimizerUtils;
+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;
+
+/**
+ * Regression test for function recompile-once issue with literal replacement.
+ * 
+ */
+public class RewritePushdownUaggTest extends AutomatedTestBase 
+{	
+	//two aggregation functions as examples
+	private static final String TEST_NAME1 = "RewritePushdownColsums";
+	private static final String TEST_NAME2 = "RewritePushdownRowsums";
+	private static final String TEST_NAME3 = "RewritePushdownColmins";
+	private static final String TEST_NAME4 = "RewritePushdownRowmins";
+	
+	private static final String TEST_DIR = "functions/misc/";
+	private static final String TEST_CLASS_DIR = TEST_DIR + RewritePushdownUaggTest.class.getSimpleName() + "/";
+	
+	private static final int rows = 192;
+	private static final int cols = 293;
+	private static final double eps = Math.pow(10, -10);
+	
+	@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" }) );
+		addTestConfiguration( TEST_NAME3, new TestConfiguration(TEST_CLASS_DIR, TEST_NAME3, new String[] { "R" }) );
+		addTestConfiguration( TEST_NAME4, new TestConfiguration(TEST_CLASS_DIR, TEST_NAME4, new String[] { "R" }) );
+	}
+
+	@Test
+	public void testRewriteColSumsNoRewrite()  {
+		testRewritePushdownUagg( TEST_NAME1, false );
+	}
+	
+	@Test
+	public void testRewriteRowSumsNoRewrite()  {
+		testRewritePushdownUagg( TEST_NAME2, false );
+	}
+	
+	@Test
+	public void testRewriteColMinsNoRewrite()  {
+		testRewritePushdownUagg( TEST_NAME3, false );
+	}
+	
+	@Test
+	public void testRewriteRowMinsNoRewrite()  {
+		testRewritePushdownUagg( TEST_NAME4, false );
+	}
+	
+	@Test
+	public void testRewriteColSums()  {
+		testRewritePushdownUagg( TEST_NAME1, true );
+	}
+	
+	@Test
+	public void testRewriteRowSums()  {
+		testRewritePushdownUagg( TEST_NAME2, true );
+	}
+	
+	@Test
+	public void testRewriteColMins()  {
+		testRewritePushdownUagg( TEST_NAME3, true );
+	}
+	
+	@Test
+	public void testRewriteRowMins()  {
+		testRewritePushdownUagg( TEST_NAME4, true );
+	}
+
+	
+	/**
+	 * 
+	 * @param condition
+	 * @param branchRemoval
+	 * @param IPA
+	 */
+	private void testRewritePushdownUagg( String testname, boolean rewrites )
+	{	
+		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", input("X"), output("R") };
+			
+			fullRScriptName = HOME + testname + ".R";
+			rCmd = getRCmd(inputDir(), expectedDir());			
+
+			OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION = rewrites;
+
+			double[][] X = getRandomMatrix(rows, cols, -1, 1, 0.56d, 7);
+			writeInputMatrixWithMTD("X", X, true);
+			
+			runTest(true, false, null, -1); 
+			runRScript(true); 
+			
+			//compare matrices 
+			HashMap<CellIndex, Double> dmlfile = readDMLMatrixFromHDFS("R");
+			HashMap<CellIndex, Double> rfile  = readRMatrixFromFS("R");
+			TestUtils.compareMatrices(dmlfile, rfile, eps, "Stat-DML", "Stat-R");
+			
+			//check matrix mult existence
+			String check = null;
+			if( testname.equals(TEST_NAME1) ) //colsums
+				check = rewrites ? "uark+" : "uack+";
+			else if( testname.equals(TEST_NAME2) ) //rowsums
+				check = rewrites ? "uack+" : "uark+";
+			else if( testname.equals(TEST_NAME3) ) //colmins
+				check = rewrites ? "uarmin" : "uacmin";
+			else if( testname.equals(TEST_NAME4) ) //rowmins
+				check = rewrites ? "uacmin" : "uarmin";
+			
+			Assert.assertTrue( "Missing opcode: "+check, Statistics.getCPHeavyHitterOpCodes().contains(check) );
+		}
+		finally
+		{
+			OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION = oldFlag;
+		}
+	}	
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/5956a612/src/test/scripts/functions/misc/RewritePushdownColmins.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/RewritePushdownColmins.R b/src/test/scripts/functions/misc/RewritePushdownColmins.R
new file mode 100644
index 0000000..4459646
--- /dev/null
+++ b/src/test/scripts/functions/misc/RewritePushdownColmins.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")
+
+X = as.matrix(readMM(paste(args[1], "X.mtx", sep="")))
+R = t(as.matrix(colMins(t(X))));
+
+writeMM(as(R, "CsparseMatrix"), paste(args[2], "R", sep="")); 

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/5956a612/src/test/scripts/functions/misc/RewritePushdownColmins.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/RewritePushdownColmins.dml b/src/test/scripts/functions/misc/RewritePushdownColmins.dml
new file mode 100644
index 0000000..90d2668
--- /dev/null
+++ b/src/test/scripts/functions/misc/RewritePushdownColmins.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.
+#
+#-------------------------------------------------------------
+
+
+X = read($1);
+R = colMins(t(X));
+
+write(R, $2);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/5956a612/src/test/scripts/functions/misc/RewritePushdownColsums.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/RewritePushdownColsums.R b/src/test/scripts/functions/misc/RewritePushdownColsums.R
new file mode 100644
index 0000000..baafefe
--- /dev/null
+++ b/src/test/scripts/functions/misc/RewritePushdownColsums.R
@@ -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.
+#
+#-------------------------------------------------------------
+
+
+args <- commandArgs(TRUE)
+options(digits=22)
+library("Matrix")
+
+X = as.matrix(readMM(paste(args[1], "X.mtx", sep="")))
+R = t(as.matrix(colSums(t(X))));
+
+writeMM(as(R, "CsparseMatrix"), paste(args[2], "R", sep="")); 

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/5956a612/src/test/scripts/functions/misc/RewritePushdownColsums.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/RewritePushdownColsums.dml b/src/test/scripts/functions/misc/RewritePushdownColsums.dml
new file mode 100644
index 0000000..2528da9
--- /dev/null
+++ b/src/test/scripts/functions/misc/RewritePushdownColsums.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.
+#
+#-------------------------------------------------------------
+
+
+X = read($1);
+R = colSums(t(X));
+
+write(R, $2);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/5956a612/src/test/scripts/functions/misc/RewritePushdownRowmins.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/RewritePushdownRowmins.R b/src/test/scripts/functions/misc/RewritePushdownRowmins.R
new file mode 100644
index 0000000..0c01834
--- /dev/null
+++ b/src/test/scripts/functions/misc/RewritePushdownRowmins.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")
+
+X = as.matrix(readMM(paste(args[1], "X.mtx", sep="")))
+R = rowMins(t(X));
+
+writeMM(as(R, "CsparseMatrix"), paste(args[2], "R", sep="")); 

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/5956a612/src/test/scripts/functions/misc/RewritePushdownRowmins.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/RewritePushdownRowmins.dml b/src/test/scripts/functions/misc/RewritePushdownRowmins.dml
new file mode 100644
index 0000000..c5f80e5
--- /dev/null
+++ b/src/test/scripts/functions/misc/RewritePushdownRowmins.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.
+#
+#-------------------------------------------------------------
+
+
+X = read($1);
+R = rowMins(t(X));
+
+write(R, $2);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/5956a612/src/test/scripts/functions/misc/RewritePushdownRowsums.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/RewritePushdownRowsums.R b/src/test/scripts/functions/misc/RewritePushdownRowsums.R
new file mode 100644
index 0000000..2de9a23
--- /dev/null
+++ b/src/test/scripts/functions/misc/RewritePushdownRowsums.R
@@ -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.
+#
+#-------------------------------------------------------------
+
+
+args <- commandArgs(TRUE)
+options(digits=22)
+library("Matrix")
+
+X = as.matrix(readMM(paste(args[1], "X.mtx", sep="")))
+R = rowSums(t(X));
+
+writeMM(as(R, "CsparseMatrix"), paste(args[2], "R", sep="")); 

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/5956a612/src/test/scripts/functions/misc/RewritePushdownRowsums.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/RewritePushdownRowsums.dml b/src/test/scripts/functions/misc/RewritePushdownRowsums.dml
new file mode 100644
index 0000000..945763e
--- /dev/null
+++ b/src/test/scripts/functions/misc/RewritePushdownRowsums.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.
+#
+#-------------------------------------------------------------
+
+
+X = read($1);
+R = rowSums(t(X));
+
+write(R, $2);
\ No newline at end of file