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/25 19:28:02 UTC

[1/3] incubator-systemml git commit: [SYSTEMML-378] Extended sparse block abstraction (block/row alignment)

Repository: incubator-systemml
Updated Branches:
  refs/heads/master 58c0d186c -> ed1511018


[SYSTEMML-378] Extended sparse block abstraction (block/row alignment)

The extended sparse block abstraction now supports alignment checks with
a second sparse block on block/row level. Non-zeros are aligned if they
exhibit the same column index and array position. Exploiting this
alignment allows for simple yet efficient co-scans over two sparse
matrices in linear time. Example scenarios occur in sparse binary and
quaternary operations. This patch also includes the related test cases.

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

Branch: refs/heads/master
Commit: f3d95cbd2a46351b012e3faca7371282daf3c3df
Parents: 58c0d18
Author: Matthias Boehm <mb...@us.ibm.com>
Authored: Sun Jan 24 20:52:15 2016 -0800
Committer: Matthias Boehm <mb...@us.ibm.com>
Committed: Sun Jan 24 20:52:15 2016 -0800

----------------------------------------------------------------------
 .../sysml/runtime/matrix/data/SparseBlock.java  |  56 +++++
 .../functions/sparse/SparseBlockAlignment.java  | 203 +++++++++++++++++++
 .../functions/sparse/ZPackageSuite.java         |   1 +
 3 files changed, 260 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/f3d95cbd/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlock.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlock.java b/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlock.java
index 0786b87..02e5f73 100644
--- a/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlock.java
+++ b/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlock.java
@@ -107,6 +107,62 @@ public abstract class SparseBlock implements Serializable
 	 */
 	public abstract boolean isContiguous();
 	
+
+	/**
+	 * Indicates if all non-zero values are aligned with the given
+	 * second sparse block instance, which can be exploited for 
+	 * more efficient operations. Two non-zeros are aligned if they 
+	 * have the same column index and reside in the same array position.
+	 * 
+	 * @param that
+	 * @return
+	 */
+	public boolean isAligned(SparseBlock that)
+	{
+		//step 1: cheap meta data comparisons
+		if( numRows() != that.numRows() ) //num rows check
+			return false;
+		
+		//step 2: check column indexes per row
+		int rlen = numRows();
+		for( int i=0; i<rlen; i++ )
+			if( !isAligned(i, that) )
+				return false;
+		
+		return true;
+	}
+	
+	/**
+	 * Indicates if all non-zero values of row r are aligned with 
+	 * the same row of the given second sparse block instance, which 
+	 * can be exploited for more efficient operations. Two non-zeros
+	 * are aligned if they have the same column index and reside in
+	 * the same array position.
+	 * 
+	 * @param r  row index starting at 0
+	 * @param that
+	 * @return
+	 */
+	public boolean isAligned(int r, SparseBlock that)
+	{
+		//step 1: cheap meta data comparisons
+		if( size(r) != that.size(r) || pos(r) != that.pos(r) ) 
+			return false;
+		
+		//step 2: check column indexes per row
+		if( !isEmpty(r) ) {
+			int alen = size(r);
+			int apos = pos(r);
+			int[] aix = indexes(r);
+			int[] bix = that.indexes(r);
+			for( int j=apos; j<apos+alen; j++ )
+				if( aix[j] != bix[j] )
+					return false;
+		}
+		
+		return true;
+	}
+	
 	/**
 	 * Clears the sparse block by deleting non-zero values. After this call
 	 * all size() calls are guaranteed to return 0.

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/f3d95cbd/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockAlignment.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockAlignment.java b/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockAlignment.java
new file mode 100644
index 0000000..6b9caa8
--- /dev/null
+++ b/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockAlignment.java
@@ -0,0 +1,203 @@
+/*
+ * 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.sparse;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.sysml.runtime.matrix.data.MatrixBlock;
+import org.apache.sysml.runtime.matrix.data.SparseBlock;
+import org.apache.sysml.runtime.matrix.data.SparseBlockCOO;
+import org.apache.sysml.runtime.matrix.data.SparseBlockCSR;
+import org.apache.sysml.runtime.matrix.data.SparseBlockMCSR;
+import org.apache.sysml.runtime.util.DataConverter;
+import org.apache.sysml.test.integration.AutomatedTestBase;
+import org.apache.sysml.test.utils.TestUtils;
+
+/**
+ * This is a sparse matrix block component test for sparse block 
+ * alignment check functionality. In order to achieve broad coverage, 
+ * we test against full/rowwise and different sparsity values.
+ * 
+ */
+public class SparseBlockAlignment extends AutomatedTestBase 
+{
+	private final static int rows = 878;
+	private final static int cols = 393;	
+	private final static double sparsity1 = 0.09;
+	private final static double sparsity2 = 0.19;
+	private final static double sparsity3 = 0.29;
+	
+	@Override
+	public void setUp() {
+		TestUtils.clearAssertionInformation();
+	}
+
+	@Test
+	public void testSparseBlockMCSR1Pos()  {
+		runSparseBlockScanTest(SparseBlock.Type.MCSR, sparsity1, true);
+	}
+	
+	@Test
+	public void testSparseBlockMCSR2Pos()  {
+		runSparseBlockScanTest(SparseBlock.Type.MCSR, sparsity2, true);
+	}
+	
+	@Test
+	public void testSparseBlockMCSR3Pos()  {
+		runSparseBlockScanTest(SparseBlock.Type.MCSR, sparsity3, true);
+	}
+	
+	@Test
+	public void testSparseBlockCSR1Pos()  {
+		runSparseBlockScanTest(SparseBlock.Type.CSR, sparsity1, true);
+	}
+	
+	@Test
+	public void testSparseBlockCSR2Pos()  {
+		runSparseBlockScanTest(SparseBlock.Type.CSR, sparsity2, true);
+	}
+	
+	@Test
+	public void testSparseBlockCSR3Pos()  {
+		runSparseBlockScanTest(SparseBlock.Type.CSR, sparsity3, true);
+	}
+	
+	@Test
+	public void testSparseBlockCOO1Pos()  {
+		runSparseBlockScanTest(SparseBlock.Type.COO, sparsity1, true);
+	}
+	
+	@Test
+	public void testSparseBlockCOO2Pos()  {
+		runSparseBlockScanTest(SparseBlock.Type.COO, sparsity2, true);
+	}
+	
+	@Test
+	public void testSparseBlockCOO3Pos()  {
+		runSparseBlockScanTest(SparseBlock.Type.COO, sparsity3, true);
+	}
+
+	@Test
+	public void testSparseBlockMCSR1Neg()  {
+		runSparseBlockScanTest(SparseBlock.Type.MCSR, sparsity1, false);
+	}
+	
+	@Test
+	public void testSparseBlockMCSR2Neg()  {
+		runSparseBlockScanTest(SparseBlock.Type.MCSR, sparsity2, false);
+	}
+	
+	@Test
+	public void testSparseBlockMCSR3Neg()  {
+		runSparseBlockScanTest(SparseBlock.Type.MCSR, sparsity3, false);
+	}
+	
+	@Test
+	public void testSparseBlockCSR1Neg()  {
+		runSparseBlockScanTest(SparseBlock.Type.CSR, sparsity1, false);
+	}
+	
+	@Test
+	public void testSparseBlockCSR2Neg()  {
+		runSparseBlockScanTest(SparseBlock.Type.CSR, sparsity2, false);
+	}
+	
+	@Test
+	public void testSparseBlockCSR3Neg()  {
+		runSparseBlockScanTest(SparseBlock.Type.CSR, sparsity3, false);
+	}
+	
+	@Test
+	public void testSparseBlockCOO1Neg()  {
+		runSparseBlockScanTest(SparseBlock.Type.COO, sparsity1, false);
+	}
+	
+	@Test
+	public void testSparseBlockCOO2Neg()  {
+		runSparseBlockScanTest(SparseBlock.Type.COO, sparsity2, false);
+	}
+	
+	@Test
+	public void testSparseBlockCOO3Neg()  {
+		runSparseBlockScanTest(SparseBlock.Type.COO, sparsity3, false);
+	}
+	
+	/**
+	 * 
+	 * @param btype
+	 * @param sparsity
+	 * @param positive
+	 */
+	private void runSparseBlockScanTest( SparseBlock.Type btype, double sparsity, boolean positive)
+	{
+		try
+		{
+			//data generation
+			double[][] A = getRandomMatrix(rows, cols, -10, 10, sparsity, 1234); 
+			
+			//init sparse block
+			SparseBlock sblock = null;
+			MatrixBlock mbtmp = DataConverter.convertToMatrixBlock(A);
+			SparseBlock srtmp = mbtmp.getSparseBlock();			
+			switch( btype ) {
+				case MCSR: sblock = new SparseBlockMCSR(srtmp); break;
+				case CSR: sblock = new SparseBlockCSR(srtmp); break;
+				case COO: sblock = new SparseBlockCOO(srtmp); break;
+			}
+			
+			//init second sparse block and deep copy
+			SparseBlock sblock2 = null;
+			switch( btype ) {
+				case MCSR: sblock2 = new SparseBlockMCSR(sblock); break;
+				case CSR: sblock2 = new SparseBlockCSR(sblock); break;
+				case COO: sblock2 = new SparseBlockCOO(sblock); break;
+			}
+			
+			//modify second block if necessary
+			if( !positive ) {
+				sblock2.deleteIndexRange(37, 0, cols-1);
+				sblock2.deleteIndexRange(38, 0, cols-1);
+			}
+			
+			//check for block comparison
+			boolean blockAligned = sblock.isAligned(sblock2);
+			if( blockAligned != positive )
+				Assert.fail("Wrong block alignment indicated: "+blockAligned+", expected: "+positive);
+			
+			//check for row comparison
+			boolean rowsAligned37 = true;
+			boolean rowsAlignedRest = true;
+			for( int i=0; i<rows; i++ ) {
+				if( i==37 || i==38 )
+					rowsAligned37 &= sblock.isAligned(i, sblock2);
+				else if( i<37 ) //CSR/COO different after update pos
+					rowsAlignedRest &= sblock.isAligned(i, sblock2);
+			}
+			if( rowsAligned37 != positive )
+				Assert.fail("Wrong row alignment indicated: "+rowsAligned37+", expected: "+positive);
+			if( !rowsAlignedRest )
+				Assert.fail("Wrong row alignment rest indicated: false.");
+		}
+		catch(Exception ex) {
+			ex.printStackTrace();
+			throw new RuntimeException(ex);
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/f3d95cbd/src/test_suites/java/org/apache/sysml/test/integration/functions/sparse/ZPackageSuite.java
----------------------------------------------------------------------
diff --git a/src/test_suites/java/org/apache/sysml/test/integration/functions/sparse/ZPackageSuite.java b/src/test_suites/java/org/apache/sysml/test/integration/functions/sparse/ZPackageSuite.java
index 01fc461..0196da1 100644
--- a/src/test_suites/java/org/apache/sysml/test/integration/functions/sparse/ZPackageSuite.java
+++ b/src/test_suites/java/org/apache/sysml/test/integration/functions/sparse/ZPackageSuite.java
@@ -26,6 +26,7 @@ import org.junit.runners.Suite;
  *  won't run two of them at once. */
 @RunWith(Suite.class)
 @Suite.SuiteClasses({
+	SparseBlockAlignment.class,
 	SparseBlockAppendSort.class,
 	SparseBlockDelete.class,
 	SparseBlockGetFirstIndex.class,


[2/3] incubator-systemml git commit: [SYSTEMML-382] Performance sparse-sparse binary matrix-matrix operations

Posted by mb...@apache.org.
[SYSTEMML-382] Performance sparse-sparse binary matrix-matrix operations

This change exploits the new sparse block alignment checks for
sparse-sparse binary matrix-matrix operations. Despite the already
linear time operation, this change improved performance by >10%. The
larger the number of columns (nnz per row), the larger the observed
improvements. 

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

Branch: refs/heads/master
Commit: eb25f160df046800a474eea567e8121e15fab110
Parents: f3d95cb
Author: Matthias Boehm <mb...@us.ibm.com>
Authored: Sun Jan 24 21:00:25 2016 -0800
Committer: Matthias Boehm <mb...@us.ibm.com>
Committed: Sun Jan 24 21:00:25 2016 -0800

----------------------------------------------------------------------
 .../runtime/matrix/data/LibMatrixBincell.java   | 48 ++++++++++++++------
 1 file changed, 34 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/eb25f160/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixBincell.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixBincell.java b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixBincell.java
index 47a46d4..2dfa7ba 100644
--- a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixBincell.java
+++ b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixBincell.java
@@ -267,22 +267,42 @@ public class LibMatrixBincell
 					SparseBlock lsblock = m1.sparseBlock;
 					SparseBlock rsblock = m2.sparseBlock;
 					
-					for(int r=0; r<rlen; r++)
+					if( ret.sparse && lsblock.isAligned(rsblock) )
 					{
-						if( !lsblock.isEmpty(r) && !rsblock.isEmpty(r) ) {
-							mergeForSparseBinary(op, lsblock.values(r), lsblock.indexes(r), lsblock.pos(r), lsblock.size(r),
-									rsblock.values(r), rsblock.indexes(r), rsblock.pos(r), rsblock.size(r), r, ret);	
-						}
-						else if( !rsblock.isEmpty(r) ) {
-							appendRightForSparseBinary(op, rsblock.values(r), rsblock.indexes(r), 
-									rsblock.pos(r), rsblock.size(r), 0, r, ret);
-						}
-						else if( !lsblock.isEmpty(r) ){
-							appendLeftForSparseBinary(op, lsblock.values(r), lsblock.indexes(r), 
-									lsblock.pos(r), lsblock.size(r), 0, r, ret);
+						SparseBlock c = ret.sparseBlock;
+						for(int r=0; r<rlen; r++) 
+							if( !lsblock.isEmpty(r) ) {
+								int alen = lsblock.size(r);
+								int apos = lsblock.pos(r);
+								int[] aix = lsblock.indexes(r);
+								double[] avals = lsblock.values(r);
+								double[] bvals = rsblock.values(r);
+								c.allocate(r, alen);
+								for( int j=apos; j<apos+alen; j++ ) {
+									double tmp = op.fn.execute(avals[j], bvals[j]);
+									c.append(r, aix[j], tmp);
+								}
+								ret.nonZeros += c.size(r);
+							}
+					}
+					else //general case
+					{	
+						for(int r=0; r<rlen; r++)
+						{
+							if( !lsblock.isEmpty(r) && !rsblock.isEmpty(r) ) {
+								mergeForSparseBinary(op, lsblock.values(r), lsblock.indexes(r), lsblock.pos(r), lsblock.size(r),
+										rsblock.values(r), rsblock.indexes(r), rsblock.pos(r), rsblock.size(r), r, ret);	
+							}
+							else if( !rsblock.isEmpty(r) ) {
+								appendRightForSparseBinary(op, rsblock.values(r), rsblock.indexes(r), 
+										rsblock.pos(r), rsblock.size(r), 0, r, ret);
+							}
+							else if( !lsblock.isEmpty(r) ){
+								appendLeftForSparseBinary(op, lsblock.values(r), lsblock.indexes(r), 
+										lsblock.pos(r), lsblock.size(r), 0, r, ret);
+							}
+							// do nothing if both not existing
 						}
-						
-						// do nothing if both not existing
 					}
 				}
 				//right sparse block existing


[3/3] incubator-systemml git commit: [SYSTEMML-382] Fix consistency sparse row deep-copy on row inserts

Posted by mb...@apache.org.
[SYSTEMML-382] Fix consistency sparse row deep-copy on row inserts

Especially with the new update in-place support we have to be careful
about shallow copies of deep rows, even if the current operation does
not modify the physical representation. This patch makes three
improvements. First, it fixes several issues introduces with the sparse
block runtime integration. Second, it extends the set row API by a flag
for deep copy requirements, which prevents unnecessary external deep
copies in case of CSR and COO. Third, it improves the performance of row
appends and specific binary-scalar operations by avoiding repeated
sparse row re-allocations. 

With this fix we can ensure result correctness again but might be too
conservative. During the rework of update in-place, we need to revisit
this and define a general policy of sparse row allocations. 

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

Branch: refs/heads/master
Commit: ed1511018656ade792385d9706a742bc0be85b4d
Parents: eb25f16
Author: Matthias Boehm <mb...@us.ibm.com>
Authored: Sun Jan 24 21:47:17 2016 -0800
Committer: Matthias Boehm <mb...@us.ibm.com>
Committed: Sun Jan 24 21:47:17 2016 -0800

----------------------------------------------------------------------
 .../runtime/matrix/data/LibMatrixBincell.java   | 10 +++---
 .../runtime/matrix/data/LibMatrixMult.java      |  4 +--
 .../runtime/matrix/data/LibMatrixReorg.java     |  4 +--
 .../sysml/runtime/matrix/data/MatrixBlock.java  | 38 +++++++++-----------
 .../sysml/runtime/matrix/data/SparseBlock.java  |  4 +--
 .../runtime/matrix/data/SparseBlockCOO.java     |  2 +-
 .../runtime/matrix/data/SparseBlockCSR.java     |  2 +-
 .../runtime/matrix/data/SparseBlockMCSR.java    |  4 +--
 8 files changed, 32 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/ed151101/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixBincell.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixBincell.java b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixBincell.java
index 2dfa7ba..593e201 100644
--- a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixBincell.java
+++ b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixBincell.java
@@ -966,7 +966,7 @@ public class LibMatrixBincell
 						double[] cvals = crow.values();
 						for(int j=0; j<alen; j++)
 							cvals[j] = (avals[apos+j] != 0) ? 1 : 0;
-						c.set(r, crow);
+						c.set(r, crow, false);
 						ret.nonZeros+=alen;
 					}
 					else //GENERAL CASE
@@ -975,7 +975,7 @@ public class LibMatrixBincell
 						if( op.fn instanceof Multiply || op.fn instanceof Multiply2 
 							|| op.fn instanceof Power2  )
 						{
-							c.allocate(r, alen, ret.clen);
+							c.allocate(r, alen);
 						}
 						
 						for(int j=apos; j<apos+alen; j++) {
@@ -1136,7 +1136,7 @@ public class LibMatrixBincell
 						
 						//temp
 						SparseRow thisRow = c.get(r);
-						c.set(r, new SparseRow(estimateSize, clen));
+						c.set(r, new SparseRow(estimateSize, clen), false);
 						
 						if(thisRow!=null)
 						{
@@ -1161,7 +1161,7 @@ public class LibMatrixBincell
 					if( !b.isEmpty(r) ) {
 						SparseRow tmp = new SparseRow( b.size(r), clen );
 						appendRightForSparseBinary(op, b.values(r), b.indexes(r), b.pos(r), b.size(r), 0, r, m1ret);
-						m1ret.sparseBlock.set(r, tmp);
+						m1ret.sparseBlock.set(r, tmp, false);
 					}
 				}				
 			}
@@ -1177,7 +1177,7 @@ public class LibMatrixBincell
 							for( int j=0; j<alen; j++ )
 								avals[j] = op.fn.execute(avals[j], 0);
 							tmp.compact(); //handle removed entries (e.g., mult, and)
-							c.set(r, tmp);
+							c.set(r, tmp, false);
 							
 							//NOTE: for left in-place, we cannot use append because it would create duplicates
 							//appendLeftForSparseBinary(op, arow.getValueContainer(), arow.getIndexContainer(), arow.size(), 0, r, m1ret);

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/ed151101/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java
index f81ea44..7e6ec48 100644
--- a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java
+++ b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java
@@ -1512,7 +1512,7 @@ public class LibMatrixMult
 							if( !m2.sparseBlock.isEmpty(aix) ) {
 								ret.rlen=m;
 								ret.allocateSparseRowsBlock(false); //allocation on demand
-								ret.sparseBlock.set(i, new SparseRow(m2.sparseBlock.get(aix))); 
+								ret.sparseBlock.set(i, m2.sparseBlock.get(aix), true); 
 								ret.nonZeros += ret.sparseBlock.size(i);
 							}
 						}
@@ -2083,7 +2083,7 @@ public class LibMatrixMult
 				}
 		
 				//memcopy entire sparse row into target position
-				c.set(bpos, new SparseRow( b.get(i) ));
+				c.set(bpos, b.get(i), true);
 				lastblk = blk;
 			}
 		}

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/ed151101/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixReorg.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixReorg.java b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixReorg.java
index bdfe7c8..388a632 100644
--- a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixReorg.java
+++ b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixReorg.java
@@ -366,7 +366,7 @@ public class LibMatrixReorg
 				for( int i=0; i<rlen; i++ ) {
 					int ix = vix[i];
 					if( !in.sparseBlock.isEmpty(ix) ) {
-						out.sparseBlock.set(i, in.sparseBlock.get(ix));
+						out.sparseBlock.set(i, in.sparseBlock.get(ix), true);
 					}
 				}
 			}
@@ -1052,7 +1052,7 @@ public class LibMatrixReorg
 		//copy all rows into target positions
 		for( int i=0; i<m; i++ ) {
 			if( !a.isEmpty(i) ) {
-				c.set(m-1-i, a.get(i));	
+				c.set(m-1-i, a.get(i), true);	
 			}
 		}
 	}

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/ed151101/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixBlock.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixBlock.java b/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixBlock.java
index 9a7bfcb..23fdb85 100644
--- a/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixBlock.java
+++ b/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixBlock.java
@@ -792,30 +792,26 @@ public class MatrixBlock extends MatrixValue implements Externalizable
 		}
 	}
 	
-	public void appendRow(int r, SparseRow values)
+	/**
+	 * 
+	 * @param r
+	 * @param row
+	 */
+	public void appendRow(int r, SparseRow row)
 	{
-		if(values==null)
+		if(row == null)
 			return;
-		if(sparse)
-		{
+		
+		if(sparse) {
 			//allocation on demand
 			allocateSparseRowsBlock(false);
-			sparseBlock.allocate(r, values.size(), -1);
-			
-			//TODO perf sparse block
-			int[] cols=values.indexes();
-			double[] vals=values.values();
-			for(int i=0; i<values.size(); i++)
-				sparseBlock.append(r, cols[i], vals[i]);
-			
-			nonZeros+=values.size();
-			
+			sparseBlock.set(r, row, true);
+			nonZeros += row.size();
 		}
-		else
-		{
-			int[] cols=values.indexes();
-			double[] vals=values.values();
-			for(int i=0; i<values.size(); i++)
+		else {
+			int[] cols = row.indexes();
+			double[] vals = row.values();
+			for(int i=0; i<row.size(); i++)
 				quickSetValue(r, cols[i], vals[i]);
 		}
 	}
@@ -1358,7 +1354,7 @@ public class MatrixBlock extends MatrixValue implements Externalizable
 		for(int i=0; i<Math.min(that.sparseBlock.numRows(), rlen); i++)
 		{
 			if(!that.sparseBlock.isEmpty(i)) {
-				sparseBlock.set(i, new SparseRow(that.sparseBlock.get(i)));				
+				sparseBlock.set(i, that.sparseBlock.get(i), true);				
 			}
 			else if(!this.sparseBlock.isEmpty(i)) {
 				this.sparseBlock.reset(i,estimatedNNzsPerRow, clen);
@@ -1797,7 +1793,7 @@ public class MatrixBlock extends MatrixValue implements Externalizable
 				{
 					if( a.isEmpty(i) ) {
 						//copy entire sparse row (no sort required)
-						a.set(i, new SparseRow(b.get(i))); 
+						a.set(i, b.get(i), true); 
 					}
 					else
 					{

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/ed151101/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlock.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlock.java b/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlock.java
index 02e5f73..10d25bd 100644
--- a/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlock.java
+++ b/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlock.java
@@ -288,9 +288,9 @@ public abstract class SparseBlock implements Serializable
 	 * 
 	 * @param r  row index starting at 0
 	 * @param row
-	 * @return
+	 * @param deep  indicator to create deep copy of sparse row
 	 */
-	public abstract void set(int r, SparseRow row);
+	public abstract void set(int r, SparseRow row, boolean deep);
 	
 	/**
 	 * Append a value to the end of the physical representation. This should 

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/ed151101/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlockCOO.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlockCOO.java b/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlockCOO.java
index 7173946..19407e1 100644
--- a/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlockCOO.java
+++ b/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlockCOO.java
@@ -303,7 +303,7 @@ public class SparseBlockCOO extends SparseBlock
 	}
 	
 	@Override
-	public void set(int r, SparseRow row) {
+	public void set(int r, SparseRow row, boolean deep) {
 		int pos = pos(r);
 		int alen = row.size();
 		int[] aix = row.indexes();

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/ed151101/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlockCSR.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlockCSR.java b/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlockCSR.java
index 7a447bd..fce7102 100644
--- a/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlockCSR.java
+++ b/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlockCSR.java
@@ -288,7 +288,7 @@ public class SparseBlockCSR extends SparseBlock
 	}
 
 	@Override
-	public void set(int r, SparseRow row) {
+	public void set(int r, SparseRow row, boolean deep) {
 		int pos = pos(r);
 		int len = size(r);		
 		int alen = row.size();

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/ed151101/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlockMCSR.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlockMCSR.java b/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlockMCSR.java
index dfddf47..637f011 100644
--- a/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlockMCSR.java
+++ b/src/main/java/org/apache/sysml/runtime/matrix/data/SparseBlockMCSR.java
@@ -231,8 +231,8 @@ public class SparseBlockMCSR extends SparseBlock
 	}
 
 	@Override
-	public void set(int r, SparseRow row) {
-		_rows[r] = row;
+	public void set(int r, SparseRow row, boolean deep) {
+		_rows[r] = deep ? new SparseRow(row) : row;
 	}
 	
 	@Override