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/04/09 07:34:38 UTC
incubator-systemml git commit: [SYSTEMML-1478] Generalized multi-agg
codegen tpl (partial shared reads)
Repository: incubator-systemml
Updated Branches:
refs/heads/master c4259eb65 -> f788b42d0
[SYSTEMML-1478] Generalized multi-agg codegen tpl (partial shared reads)
So far, we only supported multi-aggregate templates within a connected
partition of fusion plans as well as multiple aggregates over a single
shared input. This patch generalizes the compilation of multi-aggregates
to partial reads across partitions, which allows the fusion of
expressions like
r1 = sum(X * Y);
r2 = sum(X ^ 2);
r3 = sum(Y ^ 2);
into a single operator, reducing the number of reads from memory from 4
to 2. This also includes transitive partial reads for expressions like
r1 = sum(V * X);
r2 = sum(Y * Z);
r3 = sum(X * Y * Z);
where r1 does not have a shared read with r2 but when considering fusion
plans we notice that both transitively share reads with r3, reducing the
number of reads from memory from 7 to 4.
Project: http://git-wip-us.apache.org/repos/asf/incubator-systemml/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-systemml/commit/f788b42d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-systemml/tree/f788b42d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-systemml/diff/f788b42d
Branch: refs/heads/master
Commit: f788b42d09ff734d88d9c5b3bf78a5c526249f12
Parents: c4259eb
Author: Matthias Boehm <mb...@gmail.com>
Authored: Sun Apr 9 00:33:08 2017 -0700
Committer: Matthias Boehm <mb...@gmail.com>
Committed: Sun Apr 9 00:36:07 2017 -0700
----------------------------------------------------------------------
.../hops/codegen/template/CPlanMemoTable.java | 5 +
.../template/PlanSelectionFuseCostBased.java | 166 ++++++++++++++++---
.../hops/codegen/template/TemplateCell.java | 3 +-
.../hops/codegen/template/TemplateMultiAgg.java | 10 +-
.../functions/codegen/MultiAggTmplTest.java | 66 +++++++-
.../functions/codegen/multiAggPattern3.R | 33 ++++
.../functions/codegen/multiAggPattern3.dml | 29 ++++
.../functions/codegen/multiAggPattern4.R | 35 ++++
.../functions/codegen/multiAggPattern4.dml | 31 ++++
.../functions/codegen/multiAggPattern5.R | 37 +++++
.../functions/codegen/multiAggPattern5.dml | 33 ++++
.../functions/codegen/multiAggPattern6.R | 33 ++++
.../functions/codegen/multiAggPattern6.dml | 29 ++++
13 files changed, 483 insertions(+), 27 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/f788b42d/src/main/java/org/apache/sysml/hops/codegen/template/CPlanMemoTable.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/codegen/template/CPlanMemoTable.java b/src/main/java/org/apache/sysml/hops/codegen/template/CPlanMemoTable.java
index 3aa94d5..d306f0f 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/template/CPlanMemoTable.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/template/CPlanMemoTable.java
@@ -62,6 +62,11 @@ public class CPlanMemoTable
return _plans.containsKey(hopID);
}
+ public boolean contains(long hopID, TemplateType type) {
+ return contains(hopID) && get(hopID).stream()
+ .filter(p -> p.type==type).findAny().isPresent();
+ }
+
public boolean containsTopLevel(long hopID) {
return !_plansBlacklist.contains(hopID)
&& getBest(hopID) != null;
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/f788b42d/src/main/java/org/apache/sysml/hops/codegen/template/PlanSelectionFuseCostBased.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/codegen/template/PlanSelectionFuseCostBased.java b/src/main/java/org/apache/sysml/hops/codegen/template/PlanSelectionFuseCostBased.java
index 7682336..a9cd90e 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/template/PlanSelectionFuseCostBased.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/template/PlanSelectionFuseCostBased.java
@@ -25,16 +25,17 @@ import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map.Entry;
+import java.util.stream.Collectors;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.sysml.hops.AggBinaryOp;
import org.apache.sysml.hops.AggUnaryOp;
import org.apache.sysml.hops.BinaryOp;
-import org.apache.sysml.hops.DataOp;
import org.apache.sysml.hops.Hop;
import org.apache.sysml.hops.Hop.AggOp;
import org.apache.sysml.hops.Hop.Direction;
@@ -268,32 +269,91 @@ public class PlanSelectionFuseCostBased extends PlanSelection
}
}
- //across-partition multi-agg templates
- private static void createAndAddMultiAggPlans(CPlanMemoTable memo, ArrayList<Hop> roots)
+ //across-partition multi-agg templates with shared reads
+ private void createAndAddMultiAggPlans(CPlanMemoTable memo, ArrayList<Hop> roots)
{
- //#1: collect full aggregations over shared inputs (otherwise never fused)
- HashMap<Long, ArrayList<Long>> fullAggs = new HashMap<Long, ArrayList<Long>>();
+ //collect full aggregations as initial set of candidates
+ HashSet<Long> fullAggs = new HashSet<Long>();
Hop.resetVisitStatus(roots);
for( Hop hop : roots )
- rCollectAggregatesSharedRead(hop, fullAggs);
+ rCollectFullAggregates(hop, fullAggs);
+
+ //remove operators with assigned multi-agg plans
+ Iterator<Long> iter = fullAggs.iterator();
+ while( iter.hasNext() ) {
+ if( memo.contains(iter.next(), TemplateType.MultiAggTpl) )
+ iter.remove();
+ }
+
+ //check applicability for further analysis
+ if( fullAggs.size() <= 1 )
+ return;
+
+ if( LOG.isTraceEnabled() ) {
+ LOG.trace("Found across-partition ua(RC) aggregations: " +
+ Arrays.toString(fullAggs.toArray(new Long[0])));
+ }
+
+ //collect information for all candidates
+ //(subsumed aggregations, and inputs to fused operators)
+ List<AggregateInfo> aggInfos = new ArrayList<AggregateInfo>();
+ for( Long hopID : fullAggs ) {
+ Hop aggHop = memo._hopRefs.get(hopID);
+ AggregateInfo tmp = new AggregateInfo(aggHop);
+ for( Hop c : aggHop.getInput() )
+ rExtractAggregateInfo(memo, c, tmp, TemplateType.CellTpl);
+ if( tmp._fusedInputs.isEmpty() )
+ tmp.addFusedInput(aggHop.getInput().get(0).getHopID());
+ aggInfos.add(tmp);
+ }
if( LOG.isTraceEnabled() ) {
- for( Entry<Long, ArrayList<Long>> e : fullAggs.entrySet() )
- LOG.trace("Found across-partition ua(RC) aggregations for "+e.getKey()+": " +
- Arrays.toString(e.getValue().toArray(new Long[0])));
+ LOG.trace("Extracted across-partition ua(RC) aggregation info: ");
+ for( AggregateInfo info : aggInfos )
+ LOG.trace(info);
+ }
+
+ //sort aggregations by num dependencies to simplify merging
+ //clusters of aggregations with parallel dependencies
+ aggInfos = aggInfos.stream().sorted(Comparator.comparing(
+ a -> a._inputAggs.size())).collect(Collectors.toList());
+
+ //greedy grouping of multi-agg candidates
+ boolean converged = false;
+ while( !converged ) {
+ AggregateInfo merged = null;
+ for( int i=0; i<aggInfos.size(); i++ ) {
+ AggregateInfo current = aggInfos.get(i);
+ for( int j=i+1; j<aggInfos.size(); j++ ) {
+ AggregateInfo that = aggInfos.get(j);
+ if( current.isMergable(that) ) {
+ merged = current.merge(that);
+ aggInfos.remove(j); j--;
+ }
+ }
+ }
+ converged = (merged == null);
+ }
+
+ if( LOG.isTraceEnabled() ) {
+ LOG.trace("Merged across-partition ua(RC) aggregation info: ");
+ for( AggregateInfo info : aggInfos )
+ LOG.trace(info);
}
//construct and add multiagg template plans (w/ max 3 aggregations)
- for( Entry<Long, ArrayList<Long>> e : fullAggs.entrySet() ) {
- if( e.getValue().size()<=1 )
+ for( AggregateInfo info : aggInfos ) {
+ if( info._aggregates.size()<=1 )
continue;
- ArrayList<Long> aggs = e.getValue();
+ Long[] aggs = info._aggregates.keySet().toArray(new Long[0]);
MemoTableEntry me = new MemoTableEntry(TemplateType.MultiAggTpl,
- aggs.get(0), aggs.get(1), (aggs.size()>2)?aggs.get(2):-1);
- for( int i=0; i<aggs.size(); i++ ) {
- memo.add(memo._hopRefs.get(aggs.get(i)), me);
+ aggs[0], aggs[1], (aggs.length>2)?aggs[2]:-1);
+ for( int i=0; i<aggs.length; i++ ) {
+ memo.add(memo._hopRefs.get(aggs[i]), me);
+ addBestPlan(aggs[i], me);
if( LOG.isTraceEnabled() )
- LOG.trace("Added multiagg* plan: "+aggs.get(i)+" "+me);
+ LOG.trace("Added multiagg* plan: "+aggs[i]+" "+me);
+
}
}
}
@@ -321,28 +381,46 @@ public class PlanSelectionFuseCostBased extends PlanSelection
return ret;
}
- private static void rCollectAggregatesSharedRead(Hop current, HashMap<Long, ArrayList<Long>> aggs) {
+ private static void rCollectFullAggregates(Hop current, HashSet<Long> aggs) {
if( current.isVisited() )
return;
//collect all applicable full aggregations per read
if( HopRewriteUtils.isAggUnaryOp(current, AggOp.SUM, AggOp.SUM_SQ, AggOp.MIN, AggOp.MAX)
- && ((AggUnaryOp)current).getDirection()==Direction.RowCol
- && current.getInput().get(0) instanceof DataOp )
+ && ((AggUnaryOp)current).getDirection()==Direction.RowCol )
{
- Hop input = current.getInput().get(0);
- if( !aggs.containsKey(input.getHopID()) )
- aggs.put(input.getHopID(), new ArrayList<Long>());
- aggs.get(input.getHopID()).add(current.getHopID());
+ aggs.add(current.getHopID());
}
//recursively process children
for( Hop c : current.getInput() )
- rCollectAggregatesSharedRead(c, aggs);
+ rCollectFullAggregates(c, aggs);
current.setVisited();
}
+ private static void rExtractAggregateInfo(CPlanMemoTable memo, Hop current, AggregateInfo aggInfo, TemplateType type) {
+ //collect input aggregates (dependents)
+ if( HopRewriteUtils.isAggUnaryOp(current, AggOp.SUM, AggOp.SUM_SQ, AggOp.MIN, AggOp.MAX)
+ && ((AggUnaryOp)current).getDirection()==Direction.RowCol )
+ {
+ aggInfo.addInputAggregate(current.getHopID());
+ }
+
+ //recursively process children
+ MemoTableEntry me = (type!=null) ? memo.getBest(current.getHopID()) : null;
+ for( int i=0; i< current.getInput().size(); i++ ) {
+ Hop c = current.getInput().get(i);
+ if( me != null && me.isPlanRef(i) )
+ rExtractAggregateInfo(memo, c, aggInfo, type);
+ else {
+ if( type != null && c.getDataType().isMatrix() ) //add fused input
+ aggInfo.addFusedInput(c.getHopID());
+ rExtractAggregateInfo(memo, c, aggInfo, null);
+ }
+ }
+ }
+
private void selectPlans(CPlanMemoTable memo, HashSet<Long> partition, HashSet<Long> R, ArrayList<Long> M)
{
//if no materialization points, use basic fuse-all w/ partition awareness
@@ -721,4 +799,44 @@ public class PlanSelectionFuseCostBased extends PlanSelection
+Arrays.toString(inSizes.values().toArray(new Double[0]))+"}]";
}
}
+
+ private static class AggregateInfo {
+ public final HashMap<Long,Hop> _aggregates;
+ public final HashSet<Long> _inputAggs = new HashSet<Long>();
+ public final HashSet<Long> _fusedInputs = new HashSet<Long>();
+ public AggregateInfo(Hop aggregate) {
+ _aggregates = new HashMap<Long, Hop>();
+ _aggregates.put(aggregate.getHopID(), aggregate);
+ }
+ public void addInputAggregate(long hopID) {
+ _inputAggs.add(hopID);
+ }
+ public void addFusedInput(long hopID) {
+ _fusedInputs.add(hopID);
+ }
+ public boolean isMergable(AggregateInfo that) {
+ //check independence
+ boolean ret = _aggregates.size()<3
+ && _aggregates.size()+that._aggregates.size()<=3;
+ for( Long hopID : that._aggregates.keySet() )
+ ret &= !_inputAggs.contains(hopID);
+ for( Long hopID : _aggregates.keySet() )
+ ret &= !that._inputAggs.contains(hopID);
+ //check partial shared reads
+ return ret && !CollectionUtils.intersection(
+ _fusedInputs, that._fusedInputs).isEmpty();
+ }
+ public AggregateInfo merge(AggregateInfo that) {
+ _aggregates.putAll(that._aggregates);
+ _inputAggs.addAll(that._inputAggs);
+ _fusedInputs.addAll(that._fusedInputs);
+ return this;
+ }
+ @Override
+ public String toString() {
+ return "["+Arrays.toString(_aggregates.keySet().toArray(new Long[0]))+": "
+ +"{"+Arrays.toString(_inputAggs.toArray(new Long[0]))+"},"
+ +"{"+Arrays.toString(_fusedInputs.toArray(new Long[0]))+"}]";
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/f788b42d/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 885d3db..95f6643 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
@@ -150,7 +150,8 @@ public class TemplateCell extends TemplateBase
MemoTableEntry me = memo.getBest(hop.getHopID(), TemplateType.CellTpl);
for( int i=0; i<hop.getInput().size(); i++ ) {
Hop c = hop.getInput().get(i);
- if( me!=null && me.isPlanRef(i) && !(c instanceof DataOp) )
+ if( me!=null && me.isPlanRef(i) && !(c instanceof DataOp)
+ && (me.type!=TemplateType.MultiAggTpl || memo.contains(c.getHopID(), TemplateType.CellTpl)))
rConstructCplan(c, memo, tmp, inHops, compileLiterals);
else {
CNodeData cdata = TemplateUtils.createCNodeData(c, compileLiterals);
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/f788b42d/src/main/java/org/apache/sysml/hops/codegen/template/TemplateMultiAgg.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/codegen/template/TemplateMultiAgg.java b/src/main/java/org/apache/sysml/hops/codegen/template/TemplateMultiAgg.java
index aaf00e7..56477da 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/template/TemplateMultiAgg.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/template/TemplateMultiAgg.java
@@ -28,9 +28,12 @@ import java.util.stream.Collectors;
import org.apache.sysml.hops.Hop;
import org.apache.sysml.hops.Hop.AggOp;
import org.apache.sysml.hops.codegen.cplan.CNode;
+import org.apache.sysml.hops.codegen.cplan.CNodeData;
import org.apache.sysml.hops.codegen.template.CPlanMemoTable.MemoTableEntry;
import org.apache.sysml.hops.codegen.cplan.CNodeMultiAgg;
import org.apache.sysml.hops.codegen.cplan.CNodeTpl;
+import org.apache.sysml.hops.codegen.cplan.CNodeUnary;
+import org.apache.sysml.hops.codegen.cplan.CNodeUnary.UnaryType;
import org.apache.sysml.runtime.matrix.data.Pair;
public class TemplateMultiAgg extends TemplateCell
@@ -96,7 +99,12 @@ public class TemplateMultiAgg extends TemplateCell
ArrayList<CNode> outputs = new ArrayList<CNode>();
ArrayList<AggOp> aggOps = new ArrayList<AggOp>();
for( Hop root : roots ) {
- outputs.add(tmp.get(root.getHopID()));
+ CNode node = tmp.get(root.getHopID());
+ if( node instanceof CNodeData //add indexing ops for sideways data inputs
+ && ((CNodeData)inputs.get(0)).getHopID() != ((CNodeData)node).getHopID() )
+ node = new CNodeUnary(node, (roots.get(0).getDim2()==1) ?
+ UnaryType.LOOKUP_R : UnaryType.LOOKUP_RC);
+ outputs.add(node);
aggOps.add(TemplateUtils.getAggOp(root));
}
CNodeMultiAgg tpl = new CNodeMultiAgg(inputs, outputs);
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/f788b42d/src/test/java/org/apache/sysml/test/integration/functions/codegen/MultiAggTmplTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/sysml/test/integration/functions/codegen/MultiAggTmplTest.java b/src/test/java/org/apache/sysml/test/integration/functions/codegen/MultiAggTmplTest.java
index b25d496..c33d680 100644
--- a/src/test/java/org/apache/sysml/test/integration/functions/codegen/MultiAggTmplTest.java
+++ b/src/test/java/org/apache/sysml/test/integration/functions/codegen/MultiAggTmplTest.java
@@ -38,6 +38,10 @@ public class MultiAggTmplTest extends AutomatedTestBase
private static final String TEST_NAME = "multiAggPattern";
private static final String TEST_NAME1 = TEST_NAME+"1"; //min(X>7), max(X>7)
private static final String TEST_NAME2 = TEST_NAME+"2"; //sum(X>7), sum((X>7)^2)
+ private static final String TEST_NAME3 = TEST_NAME+"3"; //sum(X==7), sum(X==3)
+ private static final String TEST_NAME4 = TEST_NAME+"4"; //sum(X*Y), sum(X^2), sum(Y^2)
+ private static final String TEST_NAME5 = TEST_NAME+"5"; //sum(V*X), sum(Y*Z), sum(X+Y-Z)
+ private static final String TEST_NAME6 = TEST_NAME+"6"; //min(X), max(X), sum(X)
private static final String TEST_DIR = "functions/codegen/";
private static final String TEST_CLASS_DIR = TEST_DIR + MultiAggTmplTest.class.getSimpleName() + "/";
@@ -49,7 +53,7 @@ public class MultiAggTmplTest extends AutomatedTestBase
@Override
public void setUp() {
TestUtils.clearAssertionInformation();
- for(int i=1; i<=2; i++)
+ for(int i=1; i<=6; i++)
addTestConfiguration( TEST_NAME+i, new TestConfiguration(TEST_CLASS_DIR, TEST_NAME+i, new String[] { String.valueOf(i) }) );
}
@@ -83,6 +87,66 @@ public class MultiAggTmplTest extends AutomatedTestBase
testCodegenIntegration( TEST_NAME2, false, ExecType.SPARK );
}
+ @Test
+ public void testCodegenMultiAggRewrite3CP() {
+ testCodegenIntegration( TEST_NAME3, true, ExecType.CP );
+ }
+
+ @Test
+ public void testCodegenMultiAgg3CP() {
+ testCodegenIntegration( TEST_NAME3, false, ExecType.CP );
+ }
+
+ @Test
+ public void testCodegenMultiAgg3Spark() {
+ testCodegenIntegration( TEST_NAME3, false, ExecType.SPARK );
+ }
+
+ @Test
+ public void testCodegenMultiAggRewrite4CP() {
+ testCodegenIntegration( TEST_NAME4, true, ExecType.CP );
+ }
+
+ @Test
+ public void testCodegenMultiAgg4CP() {
+ testCodegenIntegration( TEST_NAME4, false, ExecType.CP );
+ }
+
+ @Test
+ public void testCodegenMultiAgg4Spark() {
+ testCodegenIntegration( TEST_NAME4, false, ExecType.SPARK );
+ }
+
+ @Test
+ public void testCodegenMultiAggRewrite5CP() {
+ testCodegenIntegration( TEST_NAME5, true, ExecType.CP );
+ }
+
+ @Test
+ public void testCodegenMultiAgg5CP() {
+ testCodegenIntegration( TEST_NAME5, false, ExecType.CP );
+ }
+
+ @Test
+ public void testCodegenMultiAgg5Spark() {
+ testCodegenIntegration( TEST_NAME5, false, ExecType.SPARK );
+ }
+
+ @Test
+ public void testCodegenMultiAggRewrite6CP() {
+ testCodegenIntegration( TEST_NAME6, true, ExecType.CP );
+ }
+
+ @Test
+ public void testCodegenMultiAgg6CP() {
+ testCodegenIntegration( TEST_NAME6, false, ExecType.CP );
+ }
+
+ @Test
+ public void testCodegenMultiAgg6Spark() {
+ testCodegenIntegration( TEST_NAME6, 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/incubator-systemml/blob/f788b42d/src/test/scripts/functions/codegen/multiAggPattern3.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/codegen/multiAggPattern3.R b/src/test/scripts/functions/codegen/multiAggPattern3.R
new file mode 100644
index 0000000..96f0eec
--- /dev/null
+++ b/src/test/scripts/functions/codegen/multiAggPattern3.R
@@ -0,0 +1,33 @@
+#-------------------------------------------------------------
+#
+# 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(seq(1,15), 5, 3, byrow=TRUE);
+
+#disjoint partitions with shared read
+r1 = sum(X == 7)
+r2 = sum(X == 3)
+S = as.matrix(r1+r2);
+
+writeMM(as(S, "CsparseMatrix"), paste(args[2], "S", sep=""));
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/f788b42d/src/test/scripts/functions/codegen/multiAggPattern3.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/codegen/multiAggPattern3.dml b/src/test/scripts/functions/codegen/multiAggPattern3.dml
new file mode 100644
index 0000000..5836d56
--- /dev/null
+++ b/src/test/scripts/functions/codegen/multiAggPattern3.dml
@@ -0,0 +1,29 @@
+#-------------------------------------------------------------
+#
+# 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(seq(1,15), rows=5, cols=3);
+
+#disjoint partitions with shared read
+r1 = sum(X == 7)
+r2 = sum(X == 3)
+S = as.matrix(r1+r2);
+
+write(S,$1)
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/f788b42d/src/test/scripts/functions/codegen/multiAggPattern4.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/codegen/multiAggPattern4.R b/src/test/scripts/functions/codegen/multiAggPattern4.R
new file mode 100644
index 0000000..2db1c42
--- /dev/null
+++ b/src/test/scripts/functions/codegen/multiAggPattern4.R
@@ -0,0 +1,35 @@
+#-------------------------------------------------------------
+#
+# 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(seq(1,15), 5, 3, byrow=TRUE);
+Y = matrix(seq(2,16), 5, 3, byrow=TRUE);
+
+#disjoint partitions with partial shared reads
+r1 = sum(X * Y);
+r2 = sum(X ^ 2);
+r3 = sum(Y ^ 2);
+S = as.matrix(r1+r2+r3);
+
+writeMM(as(S, "CsparseMatrix"), paste(args[2], "S", sep=""));
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/f788b42d/src/test/scripts/functions/codegen/multiAggPattern4.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/codegen/multiAggPattern4.dml b/src/test/scripts/functions/codegen/multiAggPattern4.dml
new file mode 100644
index 0000000..0ca1a96
--- /dev/null
+++ b/src/test/scripts/functions/codegen/multiAggPattern4.dml
@@ -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.
+#
+#-------------------------------------------------------------
+
+X = matrix(seq(1,15), rows=5, cols=3);
+Y = matrix(seq(2,16), rows=5, cols=3);
+
+#disjoint partitions with partial shared reads
+r1 = sum(X * Y);
+r2 = sum(X ^ 2);
+r3 = sum(Y ^ 2);
+S = as.matrix(r1+r2+r3);
+
+write(S,$1)
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/f788b42d/src/test/scripts/functions/codegen/multiAggPattern5.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/codegen/multiAggPattern5.R b/src/test/scripts/functions/codegen/multiAggPattern5.R
new file mode 100644
index 0000000..e09d1c3
--- /dev/null
+++ b/src/test/scripts/functions/codegen/multiAggPattern5.R
@@ -0,0 +1,37 @@
+#-------------------------------------------------------------
+#
+# 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")
+
+V = matrix(seq(0,14), 5, 3, byrow=TRUE);
+X = matrix(seq(1,15), 5, 3, byrow=TRUE);
+Y = matrix(seq(2,16), 5, 3, byrow=TRUE);
+Z = matrix(seq(3,17), 5, 3, byrow=TRUE);
+
+#disjoint partitions with transitive partial shared reads
+r1 = sum(V * X);
+r2 = sum(Y * Z);
+r3 = sum(X * Y * Z);
+S = as.matrix(r1+r2+r3);
+
+writeMM(as(S, "CsparseMatrix"), paste(args[2], "S", sep=""));
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/f788b42d/src/test/scripts/functions/codegen/multiAggPattern5.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/codegen/multiAggPattern5.dml b/src/test/scripts/functions/codegen/multiAggPattern5.dml
new file mode 100644
index 0000000..e4d5728
--- /dev/null
+++ b/src/test/scripts/functions/codegen/multiAggPattern5.dml
@@ -0,0 +1,33 @@
+#-------------------------------------------------------------
+#
+# 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.
+#
+#-------------------------------------------------------------
+
+V = matrix(seq(0,14), rows=5, cols=3);
+X = matrix(seq(1,15), rows=5, cols=3);
+Y = matrix(seq(2,16), rows=5, cols=3);
+Z = matrix(seq(3,17), rows=5, cols=3);
+
+#disjoint partitions with transitive partial shared reads
+r1 = sum(V * X);
+r2 = sum(Y * Z);
+r3 = sum(X * Y * Z);
+S = as.matrix(r1+r2+r3);
+
+write(S,$1)
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/f788b42d/src/test/scripts/functions/codegen/multiAggPattern6.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/codegen/multiAggPattern6.R b/src/test/scripts/functions/codegen/multiAggPattern6.R
new file mode 100644
index 0000000..0c42f6d
--- /dev/null
+++ b/src/test/scripts/functions/codegen/multiAggPattern6.R
@@ -0,0 +1,33 @@
+#-------------------------------------------------------------
+#
+# 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(seq(1,15), 5, 3, byrow=TRUE);
+
+r1 = min(X);
+r2 = max(X);
+r3 = sum(X);
+S = as.matrix(r1+r2+r3);
+
+writeMM(as(S, "CsparseMatrix"), paste(args[2], "S", sep=""));
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/f788b42d/src/test/scripts/functions/codegen/multiAggPattern6.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/codegen/multiAggPattern6.dml b/src/test/scripts/functions/codegen/multiAggPattern6.dml
new file mode 100644
index 0000000..c5a315a
--- /dev/null
+++ b/src/test/scripts/functions/codegen/multiAggPattern6.dml
@@ -0,0 +1,29 @@
+#-------------------------------------------------------------
+#
+# 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(seq(1,15), rows=5, cols=3);
+
+r1 = min(X);
+r2 = max(X);
+r3 = sum(X);
+S = as.matrix(r1+r2+r3);
+
+write(S,$1)