Repository: systemml Updated Branches: refs/heads/master c382386a0 -> 63ad279fd
[SYSTEMML-2046] Large dense matrix blocks in unary/binary operations This patch extends all unary, binary, and scalar operations to support large dense matrix blocks >16GB. Additionally, this also includes minor extensions of the new dense block abstraction and a cleanup of the matrix value abstraction. Project: http://git-wip-us.apache.org/repos/asf/systemml/repo Commit: http://git-wip-us.apache.org/repos/asf/systemml/commit/63ad279f Tree: http://git-wip-us.apache.org/repos/asf/systemml/tree/63ad279f Diff: http://git-wip-us.apache.org/repos/asf/systemml/diff/63ad279f Branch: refs/heads/master Commit: 63ad279fd8a1db216ba6a99b684eaf5d703db934 Parents: c382386 Author: Matthias Boehm <mboe...@gmail.com> Authored: Sat Dec 16 18:33:23 2017 +0100 Committer: Matthias Boehm <mboe...@gmail.com> Committed: Sun Dec 17 20:50:30 2017 +0100 ---------------------------------------------------------------------- .../runtime/compress/CompressedMatrixBlock.java | 8 - .../sysml/runtime/matrix/data/CM_N_COVCell.java | 6 - .../sysml/runtime/matrix/data/DenseBlock.java | 32 ++ .../runtime/matrix/data/DenseBlockDRB.java | 20 + .../runtime/matrix/data/DenseBlockLDRB.java | 30 +- .../runtime/matrix/data/LibMatrixBincell.java | 361 ++++++++++--------- .../sysml/runtime/matrix/data/MatrixBlock.java | 141 +------- .../sysml/runtime/matrix/data/MatrixCell.java | 6 - .../sysml/runtime/matrix/data/MatrixValue.java | 3 - .../sysml/runtime/matrix/data/WeightedCell.java | 6 - 10 files changed, 285 insertions(+), 328 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/systemml/blob/63ad279f/src/main/java/org/apache/sysml/runtime/compress/CompressedMatrixBlock.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/compress/CompressedMatrixBlock.java b/src/main/java/org/apache/sysml/runtime/compress/CompressedMatrixBlock.java index 81cc9cf..e5edada 100644 --- a/src/main/java/org/apache/sysml/runtime/compress/CompressedMatrixBlock.java +++ b/src/main/java/org/apache/sysml/runtime/compress/CompressedMatrixBlock.java @@ -1926,14 +1926,6 @@ public class CompressedMatrixBlock extends MatrixBlock implements Externalizable } @Override - public void unaryOperationsInPlace(UnaryOperator op) - throws DMLRuntimeException { - printDecompressWarning("unaryOperationsInPlace"); - MatrixBlock tmp = isCompressed() ? decompress() : this; - tmp.unaryOperationsInPlace(op); - } - - @Override public MatrixValue binaryOperations(BinaryOperator op, MatrixValue thatValue, MatrixValue result) throws DMLRuntimeException { printDecompressWarning("binaryOperations", (MatrixBlock)thatValue); http://git-wip-us.apache.org/repos/asf/systemml/blob/63ad279f/src/main/java/org/apache/sysml/runtime/matrix/data/CM_N_COVCell.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/CM_N_COVCell.java b/src/main/java/org/apache/sysml/runtime/matrix/data/CM_N_COVCell.java index cd9a995..b74ff10 100644 --- a/src/main/java/org/apache/sysml/runtime/matrix/data/CM_N_COVCell.java +++ b/src/main/java/org/apache/sysml/runtime/matrix/data/CM_N_COVCell.java @@ -172,12 +172,6 @@ public class CM_N_COVCell extends MatrixValue implements WritableComparable } @Override - public void unaryOperationsInPlace(UnaryOperator op) - throws DMLRuntimeException { - throw new DMLRuntimeException("operation not supported fro WeightedCell"); - } - - @Override public void readFields(DataInput in) throws IOException { cm.w=in.readDouble(); cm.mean.read(in); http://git-wip-us.apache.org/repos/asf/systemml/blob/63ad279f/src/main/java/org/apache/sysml/runtime/matrix/data/DenseBlock.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/DenseBlock.java b/src/main/java/org/apache/sysml/runtime/matrix/data/DenseBlock.java index 3d82969..574f508 100644 --- a/src/main/java/org/apache/sysml/runtime/matrix/data/DenseBlock.java +++ b/src/main/java/org/apache/sysml/runtime/matrix/data/DenseBlock.java @@ -80,6 +80,21 @@ public abstract class DenseBlock implements Serializable public abstract int numBlocks(); /** + * Get the number of rows per block, except last one. + * + * @return number of rows in block + */ + public abstract int blockSize(); + + /** + * Get the number of rows of the given block. + * + * @param bix block index + * @return number of rows in block + */ + public abstract int blockSize(int bix); + + /** * Get the length of the dense block as the product * of row and column dimensions. * @@ -88,6 +103,15 @@ public abstract class DenseBlock implements Serializable public abstract long size(); /** + * Get the length of the given block. + * + * @param bix block index + * @return length + */ + public abstract int size(int bix); + + + /** * Get the total length of allocated blocks. * * @return capacity @@ -196,6 +220,14 @@ public abstract class DenseBlock implements Serializable public abstract void set(int r, double[] v); /** + * Copy the given dense block. + * + * @param db dense block + */ + public abstract void set(DenseBlock db); + + + /** * Get the value for a given row and column. * * @param r row index http://git-wip-us.apache.org/repos/asf/systemml/blob/63ad279f/src/main/java/org/apache/sysml/runtime/matrix/data/DenseBlockDRB.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/DenseBlockDRB.java b/src/main/java/org/apache/sysml/runtime/matrix/data/DenseBlockDRB.java index e0d9443..d2eb5ca 100644 --- a/src/main/java/org/apache/sysml/runtime/matrix/data/DenseBlockDRB.java +++ b/src/main/java/org/apache/sysml/runtime/matrix/data/DenseBlockDRB.java @@ -74,11 +74,26 @@ public class DenseBlockDRB extends DenseBlock public int numBlocks() { return 1; } + + @Override + public int blockSize() { + return rlen; + } + + @Override + public int blockSize(int bix) { + return rlen; + } @Override public long size() { return rlen * clen; } + + @Override + public int size(int bix) { + return rlen * clen; + } @Override public long capacity() { @@ -150,6 +165,11 @@ public class DenseBlockDRB extends DenseBlock public void set(int r, int c, double v) { data[pos(r, c)] = v; } + + @Override + public void set(DenseBlock db) { + System.arraycopy(db.values(0), 0, data, 0, rlen*clen); + } @Override public void set(int r, double[] v) { http://git-wip-us.apache.org/repos/asf/systemml/blob/63ad279f/src/main/java/org/apache/sysml/runtime/matrix/data/DenseBlockLDRB.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/DenseBlockLDRB.java b/src/main/java/org/apache/sysml/runtime/matrix/data/DenseBlockLDRB.java index c6ded3a..926f7ff 100644 --- a/src/main/java/org/apache/sysml/runtime/matrix/data/DenseBlockLDRB.java +++ b/src/main/java/org/apache/sysml/runtime/matrix/data/DenseBlockLDRB.java @@ -86,11 +86,26 @@ public class DenseBlockLDRB extends DenseBlock public int numBlocks() { return data.length; } + + @Override + public int blockSize() { + return blen; + } + + @Override + public int blockSize(int bix) { + return Math.min(blen, rlen-bix*blen); + } @Override public long size() { return (long)rlen * clen; } + + @Override + public int size(int bix) { + return blockSize(bix) * clen; + } @Override public long capacity() { @@ -116,7 +131,8 @@ public class DenseBlockLDRB extends DenseBlock long nnz = 0; for(int bi=index(rl); bi<index(ru); bi++) { double[] a = data[bi]; - for(int i=pos(bi), ix=pos(bi)*clen; i<blen(bi); i++, ix+=clen) + int blen = blockSize(bi); + for(int i=pos(bi), ix=pos(bi)*clen; i<blen; i++, ix+=clen) for( int j=cl; j<cu; j++ ) nnz += (a[ix+j]!=0) ? 1 : 0; } @@ -171,7 +187,13 @@ public class DenseBlockLDRB extends DenseBlock @Override public void set(int r, double[] v) { - System.arraycopy(v, 0, data[index(r)], pos(r), v.length); + System.arraycopy(v, 0, data[index(r)], pos(r), clen); + } + + @Override + public void set(DenseBlock db) { + for(int bi=0; bi<numBlocks(); bi++) + System.arraycopy(db.values(bi), 0, data[bi], 0, size(bi)); } @Override @@ -193,10 +215,6 @@ public class DenseBlockLDRB extends DenseBlock } return sb.toString(); } - - private int blen(int bix) { - return Math.min(blen, rlen-bix*blen); - } private static int blocksize(int rlen, int clen) { return Math.min(rlen, Integer.MAX_VALUE / clen); http://git-wip-us.apache.org/repos/asf/systemml/blob/63ad279f/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 e515947..6353388 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 @@ -202,10 +202,10 @@ public class LibMatrixBincell throws DMLRuntimeException { boolean skipEmpty = (op.fn instanceof Multiply - || isSparseSafeDivide(op, m2) ); + || isSparseSafeDivide(op, m2) ); //skip empty blocks (since sparse-safe) - if( m1.isEmptyBlock(false) && m2.isEmptyBlock(false) + if( m1.isEmptyBlock(false) && m2.isEmptyBlock(false) || skipEmpty && (m1.isEmptyBlock(false) || m2.isEmptyBlock(false)) ) { return; @@ -265,64 +265,79 @@ public class LibMatrixBincell return; // skip entire empty block ret.allocateDenseBlock(); - double[] a = (m1.denseBlock != null) ? m1.getDenseBlockValues() : null; - double[] b = (m2.denseBlock != null) ? m2.getDenseBlockValues() : null; - double[] c = ret.getDenseBlockValues(); - int nnz = 0; + DenseBlock da = m1.getDenseBlock(); + DenseBlock dc = ret.getDenseBlock(); + long nnz = 0; if( atype == BinaryAccessType.MATRIX_COL_VECTOR ) { - for( int i=0, ix=0; i<rlen; i++, ix+=clen ) - { - //replicate vector value - double v2 = (b==null) ? 0 : b[i]; - if( skipEmpty && v2 == 0 ) //skip empty rows - continue; - - if( isMultiply && v2 == 1 ) { //ROW COPY - //a guaranteed to be non-null (see early abort) - System.arraycopy(a, ix, c, ix, clen); - nnz += m1.recomputeNonZeros(i, i, 0, clen-1); - } - else { //GENERAL CASE - if( a != null ) - for( int j=0; j<clen; j++ ) { - c[ix+j] = op.fn.execute( a[ix+j], v2 ); - nnz += (c[ix+j] != 0) ? 1 : 0; + double[] b = m2.getDenseBlockValues(); // always single block + + for( int bi=0; bi<dc.numBlocks(); bi++ ) { + double[] a = da.values(bi); + double[] c = dc.values(bi); + int len = dc.blockSize(bi); + int off = bi * dc.blockSize(); + for( int i=0, ix=0; i<len; i++, ix+=clen ) + { + //replicate vector value + double v2 = (b==null) ? 0 : b[off+i]; + if( skipEmpty && v2 == 0 ) //skip empty rows + continue; + + if( isMultiply && v2 == 1 ) { //ROW COPY + //a guaranteed to be non-null (see early abort) + System.arraycopy(a, ix, c, ix, clen); + nnz += m1.recomputeNonZeros(i, i, 0, clen-1); + } + else { //GENERAL CASE + if( a != null ) + for( int j=0; j<clen; j++ ) { + c[ix+j] = op.fn.execute( a[ix+j], v2 ); + nnz += (c[ix+j] != 0) ? 1 : 0; + } + else { + double val = op.fn.execute( 0, v2 ); + Arrays.fill(c, ix, ix+clen, val); + nnz += (val != 0) ? clen : 0; } - else { - double val = op.fn.execute( 0, v2 ); - Arrays.fill(c, ix, ix+clen, val); - nnz += (val != 0) ? clen : 0; } } } } else if( atype == BinaryAccessType.MATRIX_ROW_VECTOR ) { - if( a==null && b==null ) { //both empty + double[] b = m2.getDenseBlockValues(); // always single block + + if( da==null && b==null ) { //both empty double v = op.fn.execute( 0, 0 ); - Arrays.fill(c, 0, rlen*clen, v); - nnz += (v != 0) ? rlen*clen : 0; + dc.set(v); + nnz += (v != 0) ? (long)rlen*clen : 0; } - else if( a==null ) //left empty + else if( da==null ) //left empty { //compute first row + double[] c = dc.values(0); for( int j=0; j<clen; j++ ) { c[j] = op.fn.execute( 0, b[j] ); nnz += (c[j] != 0) ? rlen : 0; } //copy first to all other rows - for( int i=1, ix=clen; i<rlen; i++, ix+=clen ) - System.arraycopy(c, 0, c, ix, clen); + for( int i=1; i<rlen; i++ ) + dc.set(i, c); } else //default case (incl right empty) { - for( int i=0, ix=0; i<rlen; i++, ix+=clen ) - for( int j=0; j<clen; j++ ) { - c[ix+j] = op.fn.execute( a[ix+j], ((b!=null) ? b[j] : 0) ); - nnz += (c[ix+j] != 0) ? 1 : 0; - } + for( int bi=0; bi<dc.numBlocks(); bi++ ) { + double[] a = da.values(bi); + double[] c = dc.values(bi); + int len = dc.blockSize(bi); + for( int i=0, ix=0; i<len; i++, ix+=clen ) + for( int j=0; j<clen; j++ ) { + c[ix+j] = op.fn.execute( a[ix+j], ((b!=null) ? b[j] : 0) ); + nnz += (c[ix+j] != 0) ? 1 : 0; + } + } } } @@ -466,19 +481,17 @@ public class LibMatrixBincell if(isMultiply && v2 == 1) //ROW COPY { - for( int j=0; j<clen; j++ ) - { + for( int j=0; j<clen; j++ ) { double v1 = m1.quickGetValue(i, j); - ret.appendValue(i, j, v1); + ret.appendValue(i, j, v1); } } else //GENERAL CASE { - for( int j=0; j<clen; j++ ) - { + for( int j=0; j<clen; j++ ) { double v1 = m1.quickGetValue(i, j); double v = op.fn.execute( v1, v2 ); - ret.appendValue(i, j, v); + ret.appendValue(i, j, v); } } } @@ -492,34 +505,31 @@ public class LibMatrixBincell { //note: sparse block guaranteed to be allocated (otherwise early about) SparseBlock b = m2.sparseBlock; - if( !b.isEmpty(0) ) - { - int blen = b.size(0); //always pos 0 - int[] bix = b.indexes(0); - double[] bvals = b.values(0); - for( int i=0; i<rlen; i++ ) { - //for each row iterate only over non-zeros elements in rhs - for( int j=0; j<blen; j++ ) { - double v1 = m1.quickGetValue(i, bix[j]); - double v = op.fn.execute( v1, bvals[j] ); - ret.appendValue(i, bix[j], v); - } + if( b.isEmpty(0) ) return; + int blen = b.size(0); //always pos 0 + int[] bix = b.indexes(0); + double[] bvals = b.values(0); + for( int i=0; i<rlen; i++ ) { + //for each row iterate only over non-zeros elements in rhs + for( int j=0; j<blen; j++ ) { + double v1 = m1.quickGetValue(i, bix[j]); + double v = op.fn.execute( v1, bvals[j] ); + ret.appendValue(i, bix[j], v); } } } else //GENERAL CASE { for( int i=0; i<rlen; i++ ) - for( int j=0; j<clen; j++ ) - { + for( int j=0; j<clen; j++ ) { double v1 = m1.quickGetValue(i, j); double v2 = m2.quickGetValue(0, j); //replicated vector value double v = op.fn.execute( v1, v2 ); - ret.appendValue(i, j, v); + ret.appendValue(i, j, v); } } } - + //no need to recomputeNonZeros since maintained in append value } @@ -540,8 +550,7 @@ public class LibMatrixBincell else { for(int r=0; r<rlen; r++) { double v1 = m1.quickGetValue(r, 0); - for(int c=0; c<clen; c++) - { + for(int c=0; c<clen; c++) { double v2 = m2.quickGetValue(0, c); double v = op.fn.execute( v1, v2 ); ret.appendValue(r, c, v); @@ -629,72 +638,79 @@ public class LibMatrixBincell { //specific case in order to prevent binary search on sparse inputs (see quickget and quickset) ret.allocateDenseBlock(); - final int m = ret.rlen; final int n = ret.clen; - double[] c = ret.getDenseBlockValues(); + DenseBlock dc = ret.getDenseBlock(); //1) process left input: assignment - if( m1.sparse ) //SPARSE left + if( m1.sparse && m1.sparseBlock != null ) //SPARSE left { - if( m1.sparseBlock != null ) - { - SparseBlock a = m1.sparseBlock; - - for( int i=0, ix=0; i<m; i++, ix+=n ) { - if( !a.isEmpty(i) ) - { - int apos = a.pos(i); - int alen = a.size(i); - int[] aix = a.indexes(i); - double[] avals = a.values(i); - for(int k = apos; k < apos+alen; k++) - c[ix+aix[k]] = avals[k]; - } + SparseBlock a = m1.sparseBlock; + for( int bi=0; bi<dc.numBlocks(); bi++ ) { + double[] c = dc.values(bi); + int blen = dc.blockSize(bi); + int off = bi * dc.blockSize(); + for( int i=0, ix=0; i<blen; i++, ix+=n ) { + int ai = off + i; + if( a.isEmpty(ai) ) continue; + int apos = a.pos(ai); + int alen = a.size(ai); + int[] aix = a.indexes(ai); + double[] avals = a.values(ai); + for(int k = apos; k < apos+alen; k++) + c[ix+aix[k]] = avals[k]; } } } - else //DENSE left + else if( !m1.sparse ) //DENSE left { if( !m1.isEmptyBlock(false) ) - System.arraycopy(m1.getDenseBlockValues(), 0, c, 0, m*n); + dc.set(m1.getDenseBlock()); else - ret.denseBlock.set(0); + dc.set(0); } //2) process right input: op.fn (+,-,*), * only if dense long lnnz = 0; - if( m2.sparse ) //SPARSE right + if( m2.sparse && m2.sparseBlock!=null ) //SPARSE right { - if(m2.sparseBlock!=null) - { - SparseBlock a = m2.sparseBlock; - - for( int i=0, ix=0; i<m; i++, ix+=n ) { - if( !a.isEmpty(i) ) { - int apos = a.pos(i); - int alen = a.size(i); - int[] aix = a.indexes(i); - double[] avals = a.values(i); + SparseBlock a = m2.sparseBlock; + for( int bi=0; bi<dc.numBlocks(); bi++ ) { + double[] c = dc.values(bi); + int blen = dc.blockSize(bi); + int off = bi * dc.blockSize(); + for( int i=0, ix=0; i<blen; i++, ix+=n ) { + int ai = off + i; + if( !a.isEmpty(ai) ) { + int apos = a.pos(ai); + int alen = a.size(ai); + int[] aix = a.indexes(ai); + double[] avals = a.values(ai); for(int k = apos; k < apos+alen; k++) c[ix+aix[k]] = op.fn.execute(c[ix+aix[k]], avals[k]); } //exploit temporal locality of rows - lnnz += ret.recomputeNonZeros(i, i, 0, n-1); + lnnz += ret.recomputeNonZeros(ai, ai, 0, n-1); } } } - else //DENSE right + else if( !m2.sparse ) //DENSE right { if( !m2.isEmptyBlock(false) ) { - double[] a = m2.getDenseBlockValues(); - for( int i=0; i<m*n; i++ ) { - c[i] = op.fn.execute(c[i], a[i]); - lnnz += (c[i]!=0) ? 1 : 0; + for( int bi=0; bi<dc.numBlocks(); bi++ ) { + double[] a = m2.getDenseBlock().values(bi); + double[] c = dc.values(bi); + int len = dc.size(bi); + for( int i=0; i<len; i++ ) { + c[i] = op.fn.execute(c[i], a[i]); + lnnz += (c[i]!=0) ? 1 : 0; + } } } else if(op.fn instanceof Multiply) ret.denseBlock.set(0); + else + lnnz = m1.nonZeros; } //3) recompute nnz @@ -705,18 +721,22 @@ public class LibMatrixBincell throws DMLRuntimeException { ret.allocateDenseBlock(); - final int m = ret.rlen; - final int n = ret.clen; - double[] a = m1.getDenseBlockValues(); - double[] b = m2.getDenseBlockValues(); - double[] c = ret.getDenseBlockValues(); + DenseBlock da = m1.getDenseBlock(); + DenseBlock db = m2.getDenseBlock(); + DenseBlock dc = ret.getDenseBlock(); ValueFunction fn = op.fn; //compute dense-dense binary, maintain nnz on-the-fly - int lnnz = 0; - for( int i=0; i<m*n; i++ ) { - c[i] = fn.execute(a[i], b[i]); - lnnz += (c[i]!=0)? 1 : 0; + long lnnz = 0; + for( int bi=0; bi<da.numBlocks(); bi++ ) { + double[] a = da.values(bi); + double[] b = db.values(bi); + double[] c = dc.values(bi); + int len = da.size(bi); + for( int i=0; i<len; i++ ) { + c[i] = fn.execute(a[i], b[i]); + lnnz += (c[i]!=0)? 1 : 0; + } } ret.setNonZeros(lnnz); } @@ -774,15 +794,15 @@ public class LibMatrixBincell * @param bOp binary operator * */ - private static void performBinOuterOperation(MatrixBlock mbLeft, MatrixBlock mbRight, MatrixBlock mbOut, BinaryOperator bOp) + private static void performBinOuterOperation(MatrixBlock m1, MatrixBlock m2, MatrixBlock ret, BinaryOperator bOp) throws DMLRuntimeException { - int rlen = mbLeft.rlen; - int clen = mbOut.clen; - double b[] = DataConverter.convertToDoubleVector(mbRight); - if(!mbOut.isAllocated()) - mbOut.allocateDenseBlock(); - double c[] = mbOut.getDenseBlockValues(); + int rlen = m1.rlen; + int clen = ret.clen; + double b[] = DataConverter.convertToDoubleVector(m2); + if(!ret.isAllocated()) + ret.allocateDenseBlock(); + DenseBlock dc = ret.getDenseBlock(); //pre-materialize various types used in inner loop boolean scanType1 = (bOp.fn instanceof LessThan || bOp.fn instanceof Equals @@ -794,31 +814,34 @@ public class LibMatrixBincell boolean eqNeq = (bOp.fn instanceof Equals || bOp.fn instanceof NotEquals); long lnnz = 0; - for( int r=0, off=0; r<rlen; r++, off+=clen ) { - double value = mbLeft.quickGetValue(r, 0); - int ixPos1 = Arrays.binarySearch(b, value); - int ixPos2 = ixPos1; - if( ixPos1 >= 0 ) { //match, scan to next val - if(scanType1) while( ixPos1<b.length && value==b[ixPos1] ) ixPos1++; - if(scanType2) while( ixPos2 > 0 && value==b[ixPos2-1]) --ixPos2; - } - else - ixPos2 = ixPos1 = Math.abs(ixPos1) - 1; - int start = lt ? ixPos1 : (lte||eqNeq) ? ixPos2 : 0; - int end = gt ? ixPos2 : (gte||eqNeq) ? ixPos1 : clen; - - if (bOp.fn instanceof NotEquals) { - Arrays.fill(c, off, off+start, 1.0); - Arrays.fill(c, off+end, off+clen, 1.0); - lnnz += (start+(clen-end)); - } - else if( start < end ) { - Arrays.fill(c, off+start, off+end, 1.0); - lnnz += (end-start); + for( int bi=0; bi<dc.numBlocks(); bi++ ) { + double[] c = dc.values(bi); + for( int r=bi*dc.blockSize(), off=0; r<rlen; r++, off+=clen ) { + double value = m1.quickGetValue(r, 0); + int ixPos1 = Arrays.binarySearch(b, value); + int ixPos2 = ixPos1; + if( ixPos1 >= 0 ) { //match, scan to next val + if(scanType1) while( ixPos1<b.length && value==b[ixPos1] ) ixPos1++; + if(scanType2) while( ixPos2 > 0 && value==b[ixPos2-1]) --ixPos2; + } + else + ixPos2 = ixPos1 = Math.abs(ixPos1) - 1; + int start = lt ? ixPos1 : (lte||eqNeq) ? ixPos2 : 0; + int end = gt ? ixPos2 : (gte||eqNeq) ? ixPos1 : clen; + + if (bOp.fn instanceof NotEquals) { + Arrays.fill(c, off, off+start, 1.0); + Arrays.fill(c, off+end, off+clen, 1.0); + lnnz += (start+(clen-end)); + } + else if( start < end ) { + Arrays.fill(c, off+start, off+end, 1.0); + lnnz += (end-start); + } } } - mbOut.setNonZeros(lnnz); - mbOut.examSparsity(); + ret.setNonZeros(lnnz); + ret.examSparsity(); } private static void unsafeBinary(MatrixBlock m1, MatrixBlock m2, MatrixBlock ret, BinaryOperator op) @@ -870,7 +893,7 @@ public class LibMatrixBincell } else // MATRIX - MATRIX { - //dense non-empty vectors + //dense non-empty vectors (always single block) if( m1.clen==1 && !m1.sparse && !m1.isEmptyBlock(false) && !m2.sparse && !m2.isEmptyBlock(false) ) { @@ -991,18 +1014,20 @@ public class LibMatrixBincell ret.allocateDenseBlock(); SparseBlock a = m1.sparseBlock; - double[] c = ret.getDenseBlockValues(); + DenseBlock dc = ret.getDenseBlock(); int m = m1.rlen; int n = m1.clen; //init dense result with unsafe 0-value - double cval0 = op.executeScalar(0); - Arrays.fill(c, cval0); + dc.set(op.executeScalar(0)); //compute non-zero input values - int nnz = m*n; - for(int i=0, cix=0; i<m; i++, cix+=n) { - if( !a.isEmpty(i) ) { + long nnz = m * n; + for(int bi=0; bi<dc.numBlocks(); bi++) { + int blen = dc.blockSize(bi); + double[] c = dc.values(bi); + for(int i=bi*dc.blockSize(), cix=i*n; i<blen && i<m; i++, cix+=n) { + if( a.isEmpty(i) ) continue; int apos = a.pos(i); int alen = a.size(i); int[] aix = a.indexes(i); @@ -1027,15 +1052,19 @@ public class LibMatrixBincell //allocate dense block (if necessary), incl clear nnz ret.allocateDenseBlock(true); - double[] a = m1.getDenseBlockValues(); - double[] c = ret.getDenseBlockValues(); + DenseBlock da = m1.getDenseBlock(); + DenseBlock dc = ret.getDenseBlock(); //compute scalar operation, incl nnz maintenance - int limit = m1.rlen*m1.clen; - int nnz = 0; - for( int i=0; i<limit; i++ ) { - c[i] = op.executeScalar( a[i] ); - nnz += (c[i] != 0) ? 1 : 0; + long nnz = 0; + for( int bi=0; bi<da.numBlocks(); bi++) { + double[] a = da.values(bi); + double[] c = dc.values(bi); + int limit = da.size(bi); + for( int i=0; i<limit; i++ ) { + c[i] = op.executeScalar( a[i] ); + nnz += (c[i] != 0) ? 1 : 0; + } } ret.nonZeros = nnz; } @@ -1104,20 +1133,18 @@ public class LibMatrixBincell appendRightForSparseBinary(op, b.values(r), b.indexes(r), b.pos(r), b.size(r), 0, r, m1ret); } } - } + } } else if(m1ret.sparseBlock==null) { m1ret.sparseBlock = SparseBlockFactory.createSparseBlock(rlen); - - for(int r=0; r<rlen; r++) - { + 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 //that.sparseRows==null { @@ -1143,13 +1170,12 @@ public class LibMatrixBincell else //one side dense { for(int r=0; r<rlen; r++) - for(int c=0; c<clen; c++) - { + 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); - } + } } } @@ -1161,14 +1187,11 @@ public class LibMatrixBincell if( atype == BinaryAccessType.MATRIX_COL_VECTOR ) //MATRIX - COL_VECTOR { - for(int r=0; r<rlen; r++) - { + for(int r=0; r<rlen; r++) { //replicated value double v2 = m2.quickGetValue(r, 0); - - for(int c=0; c<clen; c++) - { - double v1 = m1ret.quickGetValue(r, c); + for(int c=0; c<clen; c++) { + double v1 = m1ret.quickGetValue(r, c); double v = op.fn.execute( v1, v2 ); m1ret.quickSetValue(r, c, v); } @@ -1177,8 +1200,7 @@ public class LibMatrixBincell else if( atype == BinaryAccessType.MATRIX_ROW_VECTOR ) //MATRIX - ROW_VECTOR { for(int r=0; r<rlen; r++) - for(int c=0; c<clen; c++) - { + for(int c=0; c<clen; c++) { double v1 = m1ret.quickGetValue(r, c); double v2 = m2.quickGetValue(0, c); //replicated value double v = op.fn.execute( v1, v2 ); @@ -1188,8 +1210,7 @@ public class LibMatrixBincell else // MATRIX - MATRIX { for(int r=0; r<rlen; r++) - for(int c=0; c<clen; c++) - { + for(int c=0; c<clen; c++) { double v1 = m1ret.quickGetValue(r, c); double v2 = m2.quickGetValue(r, c); double v = op.fn.execute( v1, v2 ); http://git-wip-us.apache.org/repos/asf/systemml/blob/63ad279f/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 f307d78..7a334a4 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 @@ -1094,10 +1094,10 @@ public class MatrixBlock extends MatrixValue implements CacheBlock, Externalizab final int n = clen; //allocate target in memory-efficient CSR format - int nnz = (int) nonZeros; + int lnnz = (int) nonZeros; int[] rptr = new int[m+1]; - int[] indexes = new int[nnz]; - double[] values = new double[nnz]; + int[] indexes = new int[lnnz]; + double[] values = new double[lnnz]; for( int i=0, pos=0, aix=0; i<m; i++ ) { for(int j=0; j<n; j++, aix++) { double aval = a[aix]; @@ -1110,10 +1110,9 @@ public class MatrixBlock extends MatrixValue implements CacheBlock, Externalizab rptr[i+1]=pos; } sparseBlock = new SparseBlockCSR( - rptr, indexes, values, nnz); + rptr, indexes, values, lnnz); //update nnz and cleanup dense block - nonZeros = nnz; denseBlock = null; } @@ -2626,7 +2625,7 @@ public class MatrixBlock extends MatrixValue implements CacheBlock, Externalizab //allocate output if( ret == null ) ret = new MatrixBlock(rlen, clen, sp, this.nonZeros); - else + else ret.reset(rlen, clen, sp); //core execute @@ -2663,7 +2662,6 @@ public class MatrixBlock extends MatrixValue implements CacheBlock, Externalizab return; final int m = rlen; - final int n = clen; if( sparse && ret.sparse ) //SPARSE <- SPARSE { @@ -2691,7 +2689,7 @@ public class MatrixBlock extends MatrixValue implements CacheBlock, Externalizab } else if( sparse ) //DENSE <- SPARSE { - SparseBlock a = sparseBlock; + SparseBlock a = sparseBlock; for(int i=0; i<m; i++) { if( a.isEmpty(i) ) continue; @@ -2712,15 +2710,19 @@ public class MatrixBlock extends MatrixValue implements CacheBlock, Externalizab { //allocate dense output block ret.allocateDenseBlock(); - double[] a = getDenseBlockValues(); - double[] c = ret.getDenseBlockValues(); - int len = m * n; + DenseBlock da = getDenseBlock(); + DenseBlock dc = ret.getDenseBlock(); //unary op, incl nnz maintenance - int nnz = 0; - for( int i=0; i<len; i++ ) { - c[i] = op.fn.execute(a[i]); - nnz += (c[i] != 0) ? 1 : 0; + long nnz = 0; + for( int bi=0; bi<da.numBlocks(); bi++ ) { + double[] a = da.values(bi); + double[] c = dc.values(bi); + int len = da.size(bi); + for( int i=0; i<len; i++ ) { + c[i] = op.fn.execute(a[i]); + nnz += (c[i] != 0) ? 1 : 0; + } } ret.nonZeros = nnz; } @@ -2750,113 +2752,6 @@ public class MatrixBlock extends MatrixValue implements CacheBlock, Externalizab } @Override - public void unaryOperationsInPlace(UnaryOperator op) - throws DMLRuntimeException - { - if(op.sparseSafe) - sparseUnaryOperationsInPlace(op); - else - denseUnaryOperationsInPlace(op); - } - - /** - * only apply to non zero cells - * - * @param op unary operator - * @throws DMLRuntimeException if DMLRuntimeException occurs - */ - private void sparseUnaryOperationsInPlace(UnaryOperator op) - throws DMLRuntimeException - { - //early abort possible since sparse-safe - if( isEmptyBlock(false) ) - return; - - if(sparse) - { - nonZeros=0; - for(int r=0; r<Math.min(rlen, sparseBlock.numRows()); r++) - { - if(sparseBlock.isEmpty(r)) - continue; - - int apos = sparseBlock.pos(r); - int alen = sparseBlock.size(r); - int[] aix = sparseBlock.indexes(r); - double[] avals = sparseBlock.values(r); - - int pos=0; - for(int i=apos; i<apos+alen; i++) - { - double v=op.fn.execute(avals[i]); - if(v!=0) { - avals[pos]=v; - aix[pos]=aix[i]; - pos++; - nonZeros++; - } - } - //TODO perf sparse block: truncate replaced by deleteIndexrange - sparseBlock.deleteIndexRange(r, pos, clen); - } - - } - else - { - double[] a = getDenseBlockValues(); - int limit = rlen*clen; - long nnz = 0; - for(int i=0; i<limit; i++) { - a[i] = op.fn.execute(a[i]); - if(a[i] != 0) - nnz++; - } - nonZeros = nnz; - } - } - - private void denseUnaryOperationsInPlace(UnaryOperator op) - throws DMLRuntimeException - { - if( sparse ) //SPARSE MATRIX - { - double v; - for(int r=0; r<rlen; r++) - for(int c=0; c<clen; c++) - { - v=op.fn.execute(quickGetValue(r, c)); - quickSetValue(r, c, v); - } - } - else//DENSE MATRIX - { - //early abort not possible because not sparsesafe - if(denseBlock==null) - allocateDenseBlock(); - - //compute values in-place and update nnz - double[] a = getDenseBlockValues(); - final int limit = rlen*clen; - int lnnz = 0; - for( int i=0; i<limit; i++ ) { - a[i] = op.fn.execute(a[i]); - if( a[i]!=0 ) - lnnz++; - } - nonZeros = lnnz; - - //IBM JVM bug (JDK6) causes crash for certain inputs (w/ infinities) - //nonZeros = 0; - //for(int i=0; i<limit; i++) - //{ - // denseBlock[i]=op.fn.execute(denseBlock[i]); - // if(denseBlock[i]!=0) - // nonZeros++; - //} - } - } - - @Override public MatrixValue binaryOperations(BinaryOperator op, MatrixValue thatValue, MatrixValue result) throws DMLRuntimeException { @@ -2869,7 +2764,7 @@ public class MatrixBlock extends MatrixValue implements CacheBlock, Externalizab //compute output dimensions boolean outer = (LibMatrixBincell.getBinaryAccessType(this, that) - == BinaryAccessType.OUTER_VECTOR_VECTOR); + == BinaryAccessType.OUTER_VECTOR_VECTOR); int rows = rlen; int cols = outer ? that.clen : clen; http://git-wip-us.apache.org/repos/asf/systemml/blob/63ad279f/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixCell.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixCell.java b/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixCell.java index 7e82c43..b1190ad 100644 --- a/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixCell.java +++ b/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixCell.java @@ -266,12 +266,6 @@ public class MatrixCell extends MatrixValue implements WritableComparable, Seria return c3; } - @Override - public void unaryOperationsInPlace(UnaryOperator op) - throws DMLRuntimeException { - value=op.fn.execute(value); - } - public int compareTo(MatrixCell o) { return Double.compare(this.value, o.value); } http://git-wip-us.apache.org/repos/asf/systemml/blob/63ad279f/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixValue.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixValue.java b/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixValue.java index e0a9579..c6361bc 100644 --- a/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixValue.java +++ b/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixValue.java @@ -41,7 +41,6 @@ import org.apache.sysml.runtime.util.UtilFunctions; @SuppressWarnings("rawtypes") public abstract class MatrixValue implements WritableComparable { - static public class CellIndex { public int row; public int column; @@ -152,8 +151,6 @@ public abstract class MatrixValue implements WritableComparable public abstract MatrixValue unaryOperations(UnaryOperator op, MatrixValue result) throws DMLRuntimeException; - - public abstract void unaryOperationsInPlace(UnaryOperator op) throws DMLRuntimeException; public abstract void incrementalAggregate(AggregateOperator aggOp, MatrixValue correction, MatrixValue newWithCorrection) throws DMLRuntimeException; http://git-wip-us.apache.org/repos/asf/systemml/blob/63ad279f/src/main/java/org/apache/sysml/runtime/matrix/data/WeightedCell.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/WeightedCell.java b/src/main/java/org/apache/sysml/runtime/matrix/data/WeightedCell.java index f111111..faad3d2 100644 --- a/src/main/java/org/apache/sysml/runtime/matrix/data/WeightedCell.java +++ b/src/main/java/org/apache/sysml/runtime/matrix/data/WeightedCell.java @@ -174,10 +174,4 @@ public class WeightedCell extends MatrixCell c3.setWeight(weight); return c3; } - - @Override - public void unaryOperationsInPlace(UnaryOperator op) - throws DMLRuntimeException { - value=op.fn.execute(value); - } }