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);
 		}
 	}