You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@systemml.apache.org by mb...@apache.org on 2018/06/22 00:40:09 UTC

systemml git commit: [MINOR] Performance binary in-place operations, especially plus

Repository: systemml
Updated Branches:
  refs/heads/master 08f9e3e47 -> 36c217d38


[MINOR] Performance binary in-place operations, especially plus

This patch makes a minor performance improvement to binary in-place
operations for dense-dense and dense-sparse ops, especially plus. On a
scenario of paramserv ASP, 10 epochs 80 workers, this patch improved the
end-to-end runtime from 212s to 202.


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

Branch: refs/heads/master
Commit: 36c217d38efe8ce031b568a799a9b796a64a1968
Parents: 08f9e3e
Author: Matthias Boehm <mb...@gmail.com>
Authored: Thu Jun 21 17:40:36 2018 -0700
Committer: Matthias Boehm <mb...@gmail.com>
Committed: Thu Jun 21 17:40:36 2018 -0700

----------------------------------------------------------------------
 .../runtime/matrix/data/LibMatrixBincell.java   | 70 ++++++++++++--------
 1 file changed, 42 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/systemml/blob/36c217d3/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 8310e72..48fce40 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
@@ -1082,10 +1082,12 @@ public class LibMatrixBincell
 
 	private static void safeBinaryInPlace(MatrixBlock m1ret, MatrixBlock m2, BinaryOperator op) {
 		//early abort on skip and empty 
-		if( m1ret.isEmptyBlock(false) && m2.isEmptyBlock(false) )
+		if( (m1ret.isEmpty() && m2.isEmpty() )
+			|| (op.fn instanceof Plus && m2.isEmpty())
+			|| (op.fn instanceof Minus && m2.isEmpty()))
 			return; // skip entire empty block
 		//special case: start aggregation
-		else if( op.fn instanceof Plus && m1ret.isEmptyBlock(false) ){
+		else if( op.fn instanceof Plus && m1ret.isEmpty() ){
 			m1ret.copy(m2);
 			return; 
 		}
@@ -1094,6 +1096,8 @@ public class LibMatrixBincell
 			safeBinaryInPlaceSparse(m1ret, m2, op);
 		else if(!m1ret.sparse && !m2.sparse)
 			safeBinaryInPlaceDense(m1ret, m2, op);
+		else if(m2.sparse && (op.fn instanceof Plus || op.fn instanceof Minus))
+			safeBinaryInPlaceDenseSparseAdd(m1ret, m2, op);
 		else //GENERIC
 			safeBinaryInPlaceGeneric(m1ret, m2, op);
 	}
@@ -1191,6 +1195,14 @@ public class LibMatrixBincell
 				}
 			}
 		}
+		else if( op.fn instanceof Plus ) {
+			for(int r=0; r<rlen; r++) {
+				int aix = a.pos(r), bix = b.pos(r);
+				double[] avals = a.values(r), bvals = b.values(r);
+				LibMatrixMult.vectAdd(bvals, avals, bix, aix, clen);
+				lnnz += UtilFunctions.computeNnz(avals, aix, clen);
+			}
+		}
 		else {
 			for(int r=0; r<rlen; r++) {
 				double[] avals = a.values(r), bvals = b.values(r);
@@ -1204,36 +1216,38 @@ public class LibMatrixBincell
 		m1ret.setNonZeros(lnnz);
 	}
 	
+	private static void safeBinaryInPlaceDenseSparseAdd(MatrixBlock m1ret, MatrixBlock m2, BinaryOperator op) {
+		final int rlen = m1ret.rlen;
+		DenseBlock a = m1ret.denseBlock;
+		SparseBlock b = m2.sparseBlock;
+		long nnz = m1ret.getNonZeros();
+		for(int r=0; r<rlen; r++) {
+			if( b.isEmpty(r) ) continue;
+			int apos = a.pos(r), bpos = b.pos(r);
+			int blen = b.size(r);
+			int[] bix = b.indexes(r);
+			double[] avals = a.values(r), bvals = b.values(r);
+			for(int k = bpos; k<bpos+blen; k++) {
+				double vold = avals[apos+bix[k]];
+				double vnew = op.fn.execute(vold, bvals[k]);
+				nnz += (vold == 0 && vnew != 0) ? 1 :
+					(vold != 0 && vnew ==0) ? -1  : 0;
+				avals[apos+bix[k]] = vnew;
+			}
+		}
+		m1ret.setNonZeros(nnz);
+	}
+	
 	private static void safeBinaryInPlaceGeneric(MatrixBlock m1ret, MatrixBlock m2, BinaryOperator op) {
 		final int rlen = m1ret.rlen;
 		final int clen = m1ret.clen;
-		
-		if( m2.sparse && (op.fn instanceof Plus || op.fn instanceof Minus) ) {
-			if( m2.isEmptyBlock(false) )
-				return;
-			SparseBlock b = m2.sparseBlock;
-			for(int r=0; r<rlen; r++) {
-				if( b.isEmpty(r) ) continue;
-				int bpos = b.pos(r);
-				int blen = b.size(r);
-				int[] bix = b.indexes(r);
-				double[] bvals = b.values(r);
-				for(int k = bpos; k<bpos+blen; k++) {
-					double vold = m1ret.quickGetValue(r, bix[k]);
-					double vnew = op.fn.execute(vold, bvals[k]);
-					m1ret.quickSetValue(r, bix[k], vnew);
-				}
+		for(int r=0; r<rlen; r++)
+			for(int c=0; c<clen; c++) {
+				double thisvalue = m1ret.quickGetValue(r, c);
+				double thatvalue = m2.quickGetValue(r, c);
+				double resultvalue = op.fn.execute(thisvalue, thatvalue);
+				m1ret.quickSetValue(r, c, resultvalue);
 			}
-		}
-		else {
-			for(int r=0; r<rlen; r++)
-				for(int c=0; c<clen; c++) {
-					double thisvalue = m1ret.quickGetValue(r, c);
-					double thatvalue = m2.quickGetValue(r, c);
-					double resultvalue = op.fn.execute(thisvalue, thatvalue);
-					m1ret.quickSetValue(r, c, resultvalue);
-				}
-		}
 	}
 	
 	private static void unsafeBinaryInPlace(MatrixBlock m1ret, MatrixBlock m2, BinaryOperator op)