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 <[email protected]> Authored: Thu Jun 21 17:40:36 2018 -0700 Committer: Matthias Boehm <[email protected]> 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)
