You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@systemml.apache.org by ni...@apache.org on 2016/09/28 00:22:17 UTC
incubator-systemml git commit: [SYSTEMML-948] Handle empty blocks in
convolution-related operation
Repository: incubator-systemml
Updated Branches:
refs/heads/master 055e850fc -> 2636d4556
[SYSTEMML-948] Handle empty blocks in convolution-related operation
Project: http://git-wip-us.apache.org/repos/asf/incubator-systemml/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-systemml/commit/2636d455
Tree: http://git-wip-us.apache.org/repos/asf/incubator-systemml/tree/2636d455
Diff: http://git-wip-us.apache.org/repos/asf/incubator-systemml/diff/2636d455
Branch: refs/heads/master
Commit: 2636d455669ea7f3707f1f93a49a17acfb7f8ca8
Parents: 055e850
Author: Niketan Pansare <np...@us.ibm.com>
Authored: Fri Sep 23 15:39:48 2016 -0700
Committer: Niketan Pansare <np...@us.ibm.com>
Committed: Tue Sep 27 17:15:18 2016 -0700
----------------------------------------------------------------------
.../cp/ConvolutionCPInstruction.java | 59 +++++++++----
.../sysml/runtime/matrix/data/LibMatrixDNN.java | 92 +++++++++++---------
2 files changed, 94 insertions(+), 57 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/2636d455/src/main/java/org/apache/sysml/runtime/instructions/cp/ConvolutionCPInstruction.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/instructions/cp/ConvolutionCPInstruction.java b/src/main/java/org/apache/sysml/runtime/instructions/cp/ConvolutionCPInstruction.java
index 5e83ffa..3885720 100644
--- a/src/main/java/org/apache/sysml/runtime/instructions/cp/ConvolutionCPInstruction.java
+++ b/src/main/java/org/apache/sysml/runtime/instructions/cp/ConvolutionCPInstruction.java
@@ -180,40 +180,65 @@ public class ConvolutionCPInstruction extends UnaryCPInstruction {
ConvolutionParameters params = new ConvolutionParameters(N, C, H, W, K, R, S, stride_h, stride_w, pad_h, pad_w, _numThreads);
if (instOpcode.equalsIgnoreCase("maxpooling")) {
- // Is eligible for REUSE_NONZEROED_OUTPUT but cannot guarantee that previous output has been rmvar-ed
- // without somewhat expensive HashMap checks
- outputBlock = getDenseOutputBlock(ec, N, C*P*Q, true);
- params.setReuseNonZeroedOutput(_reuseNonZeroedOutput);
+ if(matBlock.isEmptyBlock()) {
+ outputBlock = new MatrixBlock(N, C*P*Q, true, 0);
+ }
+ else {
+ // Is eligible for REUSE_NONZEROED_OUTPUT but cannot guarantee that previous output has been rmvar-ed
+ // without somewhat expensive HashMap checks
+ outputBlock = getDenseOutputBlock(ec, N, C*P*Q, true);
+ params.setReuseNonZeroedOutput(_reuseNonZeroedOutput);
+ }
LibMatrixDNN.maxpooling(matBlock, outputBlock, params);
}
else if (instOpcode.equalsIgnoreCase("maxpooling_backward")) {
MatrixBlock dout = ec.getMatrixInput(_in2.getName());
- // Is eligible for REUSE_NONZEROED_OUTPUT but cannot guarantee that previous output has been rmvar-ed
- // without somewhat expensive HashMap checks
- outputBlock = getDenseOutputBlock(ec, N, C*H*W, false);
- params.setReuseNonZeroedOutput(_reuseNonZeroedOutput);
+ if(matBlock.isEmptyBlock() || dout.isEmptyBlock()) {
+ outputBlock = new MatrixBlock(N, C*H*W, true, 0);
+ }
+ else {
+ // Is eligible for REUSE_NONZEROED_OUTPUT but cannot guarantee that previous output has been rmvar-ed
+ // without somewhat expensive HashMap checks
+ outputBlock = getDenseOutputBlock(ec, N, C*H*W, false);
+ params.setReuseNonZeroedOutput(_reuseNonZeroedOutput);
+ }
LibMatrixDNN.maxpooling_backward(matBlock, dout, outputBlock, params);
ec.releaseMatrixInput(_in2.getName());
}
else if (instOpcode.equalsIgnoreCase("conv2d")) {
MatrixBlock filter = ec.getMatrixInput(_in2.getName());
- outputBlock = getDenseOutputBlock(ec, N, K*P*Q, false);
- params.setReuseNonZeroedOutput(_reuseNonZeroedOutput);
- LibMatrixDNN.conv2d(matBlock, filter, outputBlock, params);
+ if(filter.isEmptyBlock() || matBlock.isEmptyBlock()) {
+ outputBlock = new MatrixBlock(N, K*P*Q, true, 0);
+ }
+ else {
+ outputBlock = getDenseOutputBlock(ec, N, K*P*Q, false);
+ params.setReuseNonZeroedOutput(_reuseNonZeroedOutput);
+ LibMatrixDNN.conv2d(matBlock, filter, outputBlock, params);
+ }
ec.releaseMatrixInput(_in2.getName());
}
else if (instOpcode.equalsIgnoreCase("conv2d_backward_filter")) {
MatrixBlock dout = ec.getMatrixInput(_in2.getName());
- outputBlock = getDenseOutputBlock(ec, K, C*R*S, false);
- params.setReuseNonZeroedOutput(_reuseNonZeroedOutput);
- LibMatrixDNN.conv2d_backward_filter(matBlock, dout, outputBlock, params);
+ if(dout.isEmptyBlock() || matBlock.isEmptyBlock()) {
+ outputBlock = new MatrixBlock(K, C*R*S, true, 0);
+ }
+ else {
+ outputBlock = getDenseOutputBlock(ec, K, C*R*S, false);
+ params.setReuseNonZeroedOutput(_reuseNonZeroedOutput);
+ LibMatrixDNN.conv2d_backward_filter(matBlock, dout, outputBlock, params);
+ }
ec.releaseMatrixInput(_in2.getName());
}
else if (instOpcode.equalsIgnoreCase("conv2d_backward_data")) {
MatrixBlock dout = ec.getMatrixInput(_in2.getName());
- outputBlock = getDenseOutputBlock(ec, N, C * H * W, false);
- params.setReuseNonZeroedOutput(_reuseNonZeroedOutput);
- LibMatrixDNN.conv2d_backward_data(matBlock, dout, outputBlock, params);
+ if(dout.isEmptyBlock() || matBlock.isEmptyBlock()) {
+ outputBlock = new MatrixBlock(N, C * H * W, true, 0);
+ }
+ else {
+ outputBlock = getDenseOutputBlock(ec, N, C * H * W, false);
+ params.setReuseNonZeroedOutput(_reuseNonZeroedOutput);
+ LibMatrixDNN.conv2d_backward_data(matBlock, dout, outputBlock, params);
+ }
ec.releaseMatrixInput(_in2.getName());
}
else {
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/2636d455/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixDNN.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixDNN.java b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixDNN.java
index c2b3f7d..e785112 100644
--- a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixDNN.java
+++ b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixDNN.java
@@ -331,12 +331,14 @@ public class LibMatrixDNN {
}
}
else if(!ret.isInSparseFormat() && elem.isInSparseFormat()) {
- Iterator<IJV> iter = elem.sparseBlock.getIterator();
- int numCol = ret.getNumColumns();
- while(iter.hasNext()) {
- IJV ijv = iter.next();
- int index = ijv.getI()*numCol + ijv.getJ();
- ret.denseBlock[index] += ijv.getV();
+ if(!elem.isEmptyBlock()) {
+ Iterator<IJV> iter = elem.sparseBlock.getIterator();
+ int numCol = ret.getNumColumns();
+ while(iter.hasNext()) {
+ IJV ijv = iter.next();
+ int index = ijv.getI()*numCol + ijv.getJ();
+ ret.denseBlock[index] += ijv.getV();
+ }
}
}
else {
@@ -360,11 +362,13 @@ public class LibMatrixDNN {
}
}
else if(!ret.isInSparseFormat() && elem.isInSparseFormat()) {
- Iterator<IJV> iter = elem.sparseBlock.getIterator();
- while(iter.hasNext()) {
- IJV ijv = iter.next();
- int index = ijv.getJ()*numRow + ijv.getI();
- ret.denseBlock[index] += ijv.getV();
+ if(!elem.isEmptyBlock()) {
+ Iterator<IJV> iter = elem.sparseBlock.getIterator();
+ while(iter.hasNext()) {
+ IJV ijv = iter.next();
+ int index = ijv.getJ()*numRow + ijv.getI();
+ ret.denseBlock[index] += ijv.getV();
+ }
}
}
else {
@@ -411,8 +415,8 @@ public class LibMatrixDNN {
loopedConvBwdFilterMatMultTime.addAndGet(t4-t3);
loopedConvBwdFilterIm2ColTime.addAndGet(t2-t1);
}
-
- elementWiseInPlaceTransposedAddition(partialRetBlock, temp);
+ if(!temp.isEmptyBlock())
+ elementWiseInPlaceTransposedAddition(partialRetBlock, temp);
return partialRetBlock;
}
@@ -432,11 +436,6 @@ public class LibMatrixDNN {
throw new DMLRuntimeException("Incorrect input to conv2d");
}
- // Convert filter (which is relatively small matrix) to dense
- if(params.input2.isInSparseFormat()) {
- params.input2.sparseToDense();
- }
-
if(DMLScript.STATISTICS) {
if(input.isInSparseFormat() || filter.isInSparseFormat()) {
conv2dSparseCount.addAndGet(1);
@@ -479,19 +478,26 @@ public class LibMatrixDNN {
loopedConvMatMultTime.addAndGet(t3 - t2);
}
- if(matMultOutBlock.isInSparseFormat()) {
- Iterator<IJV> iter = matMultOutBlock.sparseBlock.getIterator();
- final int outOffset = n*params.K*params.P*params.Q;
- while(iter.hasNext()) {
- IJV ijv = iter.next();
- int k = ijv.getI();
- int p = ijv.getJ() / params.Q;
- int q = ijv.getJ() % params.Q;
- params.output.denseBlock[outOffset + k*params.P*params.Q + p*params.Q + q] = ijv.getV();
+ int destPos = n*params.K*params.P*params.Q;
+ int length = params.K*params.P*params.Q;
+ if(params.reuseNonZeroedOutput && matMultOutBlock.isEmptyBlock()) {
+ Arrays.fill(params.output.denseBlock, destPos, destPos + length, 0);
+ }
+ else if(!matMultOutBlock.isEmptyBlock()) {
+ if(matMultOutBlock.isInSparseFormat()) {
+ Iterator<IJV> iter = matMultOutBlock.sparseBlock.getIterator();
+ final int outOffset = n*params.K*params.P*params.Q;
+ while(iter.hasNext()) {
+ IJV ijv = iter.next();
+ int k = ijv.getI();
+ int p = ijv.getJ() / params.Q;
+ int q = ijv.getJ() % params.Q;
+ params.output.denseBlock[outOffset + k*params.P*params.Q + p*params.Q + q] = ijv.getV();
+ }
}
+ else
+ System.arraycopy(matMultOutBlock.denseBlock, 0, params.output.denseBlock, destPos, length);
}
- else
- System.arraycopy(matMultOutBlock.denseBlock, 0, params.output.denseBlock, n*params.K*params.P*params.Q, params.K*params.P*params.Q);
}
@@ -583,6 +589,7 @@ public class LibMatrixDNN {
if (!params.input1.isInSparseFormat())
throw new DMLRuntimeException("Incorrect usage: Call optimized versions");
+ // params.input2.isEmptyBlock() check is done by the caller
Iterator<IJV> iter = params.input2.sparseBlock.getIterator(n, n+1);
int [] tensorIndexes = new int[3];
@@ -599,12 +606,13 @@ public class LibMatrixDNN {
start_index_h = Math.max(start_index_h, 0);
int maxIndex = getMaxIndexSparse(start_index_h, end_index_h, q, inputOffset, n, c, params.input1, params);
outputArray[maxIndex] += ijv.getV();
- }
+ }
}
private static void doPoolingBackwardDenseSparse(int n, double [] inputArray,
MatrixBlock dout, double [] outputArray, ConvolutionParameters params) throws DMLRuntimeException {
+ // dout.isEmptyBlock() check is done by the caller
Iterator<IJV> iter = dout.sparseBlock.getIterator(n, n+1);
int [] tensorIndexes = new int[3];
@@ -648,6 +656,7 @@ public class LibMatrixDNN {
if(!input.isInSparseFormat())
throw new DMLRuntimeException("Incorrect usage: Only sparse format supported");
+ // input.isEmptyBlock() check is done by the caller
Iterator<IJV> iter = input.sparseBlock.getIterator(n, n+1);
int [] tensorIndexes = new int[3];
@@ -784,15 +793,17 @@ public class LibMatrixDNN {
if(zeroOutSparseOutput)
Arrays.fill(outputArray, 0);
- Iterator<IJV> iter = input.sparseBlock.getIterator(inputN, inputN+1);
- int [] tensorIndexes = new int[3];
- while(iter.hasNext()) {
- IJV ijv = iter.next();
- computeTensorIndexes(ijv.getJ(), tensorIndexes, params.P, params.Q);
- int k = tensorIndexes[0];
- int p = tensorIndexes[1];
- int q = tensorIndexes[2];
- outputArray[outputOffset + p*params.Q*params.K + q*params.K + k] = ijv.getV();
+ if(!input.isEmptyBlock()) {
+ Iterator<IJV> iter = input.sparseBlock.getIterator(inputN, inputN+1);
+ int [] tensorIndexes = new int[3];
+ while(iter.hasNext()) {
+ IJV ijv = iter.next();
+ computeTensorIndexes(ijv.getJ(), tensorIndexes, params.P, params.Q);
+ int k = tensorIndexes[0];
+ int p = tensorIndexes[1];
+ int q = tensorIndexes[2];
+ outputArray[outputOffset + p*params.Q*params.K + q*params.K + k] = ijv.getV();
+ }
}
}
}
@@ -961,7 +972,8 @@ public class LibMatrixDNN {
doCol2IMDenseInput(0, outputN, inputArray, outputArray, params);
}
else {
- doCol2IMSparseInput(0, outputN, input.getSparseBlockIterator(), outputArray, params);
+ if(!input.isEmptyBlock())
+ doCol2IMSparseInput(0, outputN, input.getSparseBlockIterator(), outputArray, params);
}
}