Repository: systemml Updated Branches: refs/heads/master 00d72a092 -> c7604ea26
[MINOR] Performance binary inplace ops for result merge, cleanups Project: http://git-wip-us.apache.org/repos/asf/systemml/repo Commit: http://git-wip-us.apache.org/repos/asf/systemml/commit/c7604ea2 Tree: http://git-wip-us.apache.org/repos/asf/systemml/tree/c7604ea2 Diff: http://git-wip-us.apache.org/repos/asf/systemml/diff/c7604ea2 Branch: refs/heads/master Commit: c7604ea26de0705655310adaa3b40d320d389bed Parents: 00d72a0 Author: Matthias Boehm <[email protected]> Authored: Sun Jan 28 01:15:46 2018 -0800 Committer: Matthias Boehm <[email protected]> Committed: Sun Jan 28 01:15:46 2018 -0800 ---------------------------------------------------------------------- .../parfor/ResultMergeLocalFile.java | 6 +- .../parfor/ResultMergeLocalMemory.java | 2 +- .../runtime/matrix/data/LibMatrixBincell.java | 197 +++++++++++-------- 3 files changed, 120 insertions(+), 85 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/systemml/blob/c7604ea2/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/ResultMergeLocalFile.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/ResultMergeLocalFile.java b/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/ResultMergeLocalFile.java index 6f987b2..dcb85c8 100644 --- a/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/ResultMergeLocalFile.java +++ b/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/ResultMergeLocalFile.java @@ -711,7 +711,7 @@ public class ResultMergeLocalFile extends ResultMerge } //sort sparse due to append-only - if( appendOnly && _isAccum ) + if( appendOnly && !_isAccum ) mb.sortSparseRows(); //change sparsity if required after @@ -905,7 +905,7 @@ public class ResultMergeLocalFile extends ResultMerge } //sort sparse due to append-only - if( appendOnly && _isAccum ) + if( appendOnly && !_isAccum ) mb.sortSparseRows(); //change sparsity if required after @@ -927,7 +927,7 @@ public class ResultMergeLocalFile extends ResultMerge } //sort sparse due to append-only - if( appendOnly && _isAccum ) + if( appendOnly && !_isAccum ) mb.sortSparseRows(); //change sparsity if required after http://git-wip-us.apache.org/repos/asf/systemml/blob/c7604ea2/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/ResultMergeLocalMemory.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/ResultMergeLocalMemory.java b/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/ResultMergeLocalMemory.java index b2f5907..1a74635 100644 --- a/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/ResultMergeLocalMemory.java +++ b/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/ResultMergeLocalMemory.java @@ -111,7 +111,7 @@ public class ResultMergeLocalMemory extends ResultMerge } //sort sparse due to append-only - if( appendOnly ) + if( appendOnly && !_isAccum ) outMBNew.sortSparseRows(); //change sparsity if required after http://git-wip-us.apache.org/repos/asf/systemml/blob/c7604ea2/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 3ed12ab..582a0cd 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 @@ -1084,104 +1084,139 @@ public class LibMatrixBincell return; } - int rlen = m1ret.rlen; - int clen = m1ret.clen; - if(m1ret.sparse && m2.sparse) + safeBinaryInPlaceSparse(m1ret, m2, op); + else if(!m1ret.sparse && !m2.sparse) + safeBinaryInPlaceDense(m1ret, m2, op); + else //GENERIC + safeBinaryInPlaceGeneric(m1ret, m2, op); + } + + private static void safeBinaryInPlaceSparse(MatrixBlock m1ret, MatrixBlock m2, BinaryOperator op) + throws DMLRuntimeException + { + if(m1ret.sparseBlock!=null) + m1ret.allocateSparseRowsBlock(false); + if(m2.sparseBlock!=null) + m2.allocateSparseRowsBlock(false); + SparseBlock c = m1ret.sparseBlock; + SparseBlock b = m2.sparseBlock; + + final int rlen = m1ret.rlen; + final int clen = m1ret.clen; + + if( c!=null && b!=null ) { - if(m1ret.sparseBlock!=null) - m1ret.allocateSparseRowsBlock(false); - if(m2.sparseBlock!=null) - m2.allocateSparseRowsBlock(false); - - SparseBlock c = m1ret.sparseBlock; - SparseBlock b = m2.sparseBlock; - - if( c!=null && b!=null ) + for(int r=0; r<rlen; r++) { - for(int r=0; r<rlen; r++) - { - if(c.isEmpty(r) && b.isEmpty(r)) - continue; + if(c.isEmpty(r) && b.isEmpty(r)) continue; + + if( b.isEmpty(r) ) { + int apos = c.pos(r); + int alen = c.size(r); + double[] values=c.values(r); + for(int i=apos; i<apos+alen; i++) + values[i]=op.fn.execute(values[i], 0); + } + else { + int estimateSize = Math.min(clen, (!c.isEmpty(r) ? + c.size(r) : 0) + (!b.isEmpty(r) ? b.size(r) : 0)); + SparseRow thisRow = c.get(r); + c.set(r, new SparseRowVector(estimateSize, clen), false); - if( b.isEmpty(r) ) - { - int apos = c.pos(r); - int alen = c.size(r); - double[] values=c.values(r); - for(int i=apos; i<apos+alen; i++) - values[i]=op.fn.execute(values[i], 0); - }else - { - int estimateSize=0; - if( !c.isEmpty(r) ) - estimateSize+=c.size(r); - if( !b.isEmpty(r)) - estimateSize+=b.size(r); - estimateSize=Math.min(clen, estimateSize); - - //temp - SparseRow thisRow = c.get(r); - c.set(r, new SparseRowVector(estimateSize, clen), false); - - if(thisRow!=null) - { - m1ret.nonZeros-=thisRow.size(); - mergeForSparseBinary(op, thisRow.values(), thisRow.indexes(), 0, - thisRow.size(), b.values(r), b.indexes(r), b.pos(r), b.size(r), r, m1ret); - - } - else - { - appendRightForSparseBinary(op, b.values(r), b.indexes(r), b.pos(r), b.size(r), 0, r, m1ret); - } + if(thisRow!=null) { + m1ret.nonZeros-=thisRow.size(); + mergeForSparseBinary(op, thisRow.values(), thisRow.indexes(), 0, + thisRow.size(), b.values(r), b.indexes(r), b.pos(r), b.size(r), r, m1ret); } - } - } - else if(m1ret.sparseBlock==null) - { - m1ret.sparseBlock = SparseBlockFactory.createSparseBlock(rlen); - for(int r=0; r<rlen; r++) { - if( !b.isEmpty(r) ) { - SparseRow tmp = new SparseRowVector( b.size(r), clen ); + else { appendRightForSparseBinary(op, b.values(r), b.indexes(r), b.pos(r), b.size(r), 0, r, m1ret); - m1ret.sparseBlock.set(r, tmp, false); } } } - else //that.sparseRows==null - { - if( !(op.fn instanceof Plus || op.fn instanceof Minus || op.fn instanceof Or) ) { - for(int r=0; r<rlen; r++){ - if( !c.isEmpty(r) ) - { - SparseRow tmp = c.get(r); - int alen = tmp.size(); - double[] avals = tmp.values(); - 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, 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); - } - } + } + else if( c == null ) { + m1ret.sparseBlock = SparseBlockFactory.createSparseBlock(rlen); + for(int r=0; r<rlen; r++) { + if( !b.isEmpty(r) ) { + SparseRow tmp = new SparseRowVector( 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, false); } } } - else //one side dense + else //that.sparseRows==null { - 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); + if( !(op.fn instanceof Plus || op.fn instanceof Minus || op.fn instanceof Or) ) { + for(int r=0; r<rlen; r++){ + if( !c.isEmpty(r) ) + { + SparseRow tmp = c.get(r); + int alen = tmp.size(); + double[] avals = tmp.values(); + 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, 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); + } } + } } + + m1ret.recomputeNonZeros(); } + private static void safeBinaryInPlaceDense(MatrixBlock m1ret, MatrixBlock m2, BinaryOperator op) + throws DMLRuntimeException + { + //prepare outputs + m1ret.allocateDenseBlock(); + DenseBlock a = m1ret.getDenseBlock(); + DenseBlock b = m2.getDenseBlock(); + final int rlen = m1ret.rlen; + final int clen = m1ret.clen; + + long lnnz = 0; + if( m2.isEmptyBlock(false) ) { + for(int r=0; r<rlen; r++) { + double[] avals = a.values(r); + for(int c=0, ix=a.pos(r); c<clen; c++, ix++) { + double tmp = op.fn.execute(avals[ix], 0); + lnnz += (avals[ix] = tmp) != 0 ? 1: 0; + } + } + } + else { + for(int r=0; r<rlen; r++) { + double[] avals = a.values(r), bvals = b.values(r); + for(int c=0, ix=a.pos(r); c<clen; c++, ix++) { + double tmp = op.fn.execute(avals[ix], bvals[ix]); + lnnz += (avals[ix] = tmp) != 0 ? 1 : 0; + } + } + } + + m1ret.setNonZeros(lnnz); + } + + private static void safeBinaryInPlaceGeneric(MatrixBlock m1ret, MatrixBlock m2, BinaryOperator op) + throws DMLRuntimeException + { + final int rlen = m1ret.rlen; + final int clen = m1ret.clen; + + 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) throws DMLRuntimeException { int rlen = m1ret.rlen;
