You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@systemml.apache.org by mb...@apache.org on 2018/04/23 00:13:13 UTC

[1/3] systemml git commit: [SYSTEMML-2275] Fix incorrect expected nnz on reading matrices from HDFS

Repository: systemml
Updated Branches:
  refs/heads/master f8dc5c18b -> 728b2c904


[SYSTEMML-2275] Fix incorrect expected nnz on reading matrices from HDFS

This patch fixes a severe issue (introduced with SYSTEMML-2217, i.e.,
after our 1.1 release) of incorrect expected nnz on reading matrices
from HDFS. In detail the data converter API required expected sparsity
which was incorrectly computed for (nnz x cols, rows) instead (rows x
cols, nnz). We now directly pass the nnz to the readers.


Project: http://git-wip-us.apache.org/repos/asf/systemml/repo
Commit: http://git-wip-us.apache.org/repos/asf/systemml/commit/e8774a7a
Tree: http://git-wip-us.apache.org/repos/asf/systemml/tree/e8774a7a
Diff: http://git-wip-us.apache.org/repos/asf/systemml/diff/e8774a7a

Branch: refs/heads/master
Commit: e8774a7a272d1ba4060020b143de6b969e3daabf
Parents: f8dc5c1
Author: Matthias Boehm <mb...@gmail.com>
Authored: Sun Apr 22 15:45:29 2018 -0700
Committer: Matthias Boehm <mb...@gmail.com>
Committed: Sun Apr 22 15:45:29 2018 -0700

----------------------------------------------------------------------
 .../controlprogram/caching/MatrixObject.java    |  4 +---
 .../apache/sysml/runtime/io/ReadProperties.java |  5 ++---
 .../sysml/runtime/util/DataConverter.java       | 20 +++++++-------------
 .../caching/CachingPWriteExportTest.java        | 15 +++++----------
 .../data/FullStringInitializeTest.java          |  3 ++-
 5 files changed, 17 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/systemml/blob/e8774a7a/src/main/java/org/apache/sysml/runtime/controlprogram/caching/MatrixObject.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/controlprogram/caching/MatrixObject.java b/src/main/java/org/apache/sysml/runtime/controlprogram/caching/MatrixObject.java
index 678ddc0..ca704e0 100644
--- a/src/main/java/org/apache/sysml/runtime/controlprogram/caching/MatrixObject.java
+++ b/src/main/java/org/apache/sysml/runtime/controlprogram/caching/MatrixObject.java
@@ -431,10 +431,8 @@ public class MatrixObject extends CacheableData<MatrixBlock>
 		}
 		
 		//read matrix and maintain meta data
-		double sparsity = (mc.getNonZeros() < 0) ? (iimd.getInputInfo().isTextIJV()?-1:1) :
-			OptimizerUtils.getSparsity(mc.getNonZeros(),mc.getRows(),mc.getCols());
 		MatrixBlock newData = DataConverter.readMatrixFromHDFS(fname, iimd.getInputInfo(), rlen, clen,
-				mc.getRowsPerBlock(), mc.getColsPerBlock(), sparsity, getFileFormatProperties());
+				mc.getRowsPerBlock(), mc.getColsPerBlock(), mc.getNonZeros(), getFileFormatProperties());
 		setHDFSFileExists(true);
 		
 		//sanity check correct output

http://git-wip-us.apache.org/repos/asf/systemml/blob/e8774a7a/src/main/java/org/apache/sysml/runtime/io/ReadProperties.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/io/ReadProperties.java b/src/main/java/org/apache/sysml/runtime/io/ReadProperties.java
index 7ada3e1..9ce11d9 100644
--- a/src/main/java/org/apache/sysml/runtime/io/ReadProperties.java
+++ b/src/main/java/org/apache/sysml/runtime/io/ReadProperties.java
@@ -24,12 +24,11 @@ import org.apache.sysml.runtime.matrix.data.InputInfo;
 
 public class ReadProperties 
 {
-
 	// Properties common to all file formats 
 	public String path;
 	public long rlen, clen;
 	public int brlen, bclen;
-	public double expectedSparsity;
+	public long expectedNnz;
 	public InputInfo inputInfo;
 	public boolean localFS;
 	
@@ -41,7 +40,7 @@ public class ReadProperties
 		clen = -1;
 		brlen = -1;
 		bclen = -1;
-		expectedSparsity = 0.1d;
+		expectedNnz = -1;
 		inputInfo = null;
 		localFS = false;
 	}

http://git-wip-us.apache.org/repos/asf/systemml/blob/e8774a7a/src/main/java/org/apache/sysml/runtime/util/DataConverter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/util/DataConverter.java b/src/main/java/org/apache/sysml/runtime/util/DataConverter.java
index 0c834b1..7aa50d9 100644
--- a/src/main/java/org/apache/sysml/runtime/util/DataConverter.java
+++ b/src/main/java/org/apache/sysml/runtime/util/DataConverter.java
@@ -94,7 +94,6 @@ public class DataConverter
 		prop.bclen = bclen;
 		prop.localFS = localFS;
 		
-		//expected matrix is sparse (default SystemML usecase)
 		return readMatrixFromHDFS(prop);
 	}
 
@@ -110,11 +109,10 @@ public class DataConverter
 		prop.brlen = brlen;
 		prop.bclen = bclen;
 		
-		//expected matrix is sparse (default SystemML usecase)
 		return readMatrixFromHDFS(prop);
 	}
 
-	public static MatrixBlock readMatrixFromHDFS(String dir, InputInfo inputinfo, long rlen, long clen, int brlen, int bclen, double expectedSparsity) 
+	public static MatrixBlock readMatrixFromHDFS(String dir, InputInfo inputinfo, long rlen, long clen, int brlen, int bclen, long expectedNnz) 
 		throws IOException
 	{
 		ReadProperties prop = new ReadProperties();
@@ -125,13 +123,13 @@ public class DataConverter
 		prop.clen = clen;
 		prop.brlen = brlen;
 		prop.bclen = bclen;
-		prop.expectedSparsity = expectedSparsity;
+		prop.expectedNnz = expectedNnz;
 		
 		return readMatrixFromHDFS(prop);
 	}
 
 	public static MatrixBlock readMatrixFromHDFS(String dir, InputInfo inputinfo, long rlen, long clen, 
-			int brlen, int bclen, double expectedSparsity, boolean localFS) 
+			int brlen, int bclen, long expectedNnz, boolean localFS) 
 		throws IOException
 	{
 		ReadProperties prop = new ReadProperties();
@@ -142,14 +140,14 @@ public class DataConverter
 		prop.clen = clen;
 		prop.brlen = brlen;
 		prop.bclen = bclen;
-		prop.expectedSparsity = expectedSparsity;
+		prop.expectedNnz = expectedNnz;
 		prop.localFS = localFS;
 		
 		return readMatrixFromHDFS(prop);
 	}
 
 	public static MatrixBlock readMatrixFromHDFS(String dir, InputInfo inputinfo, long rlen, long clen, 
-			int brlen, int bclen, double expectedSparsity, FileFormatProperties formatProperties) 
+			int brlen, int bclen, long expectedNnz, FileFormatProperties formatProperties) 
 	throws IOException
 	{
 		ReadProperties prop = new ReadProperties();
@@ -160,10 +158,9 @@ public class DataConverter
 		prop.clen = clen;
 		prop.brlen = brlen;
 		prop.bclen = bclen;
-		prop.expectedSparsity = expectedSparsity;
+		prop.expectedNnz = expectedNnz;
 		prop.formatProperties = formatProperties;
 		
-		//prop.printMe();
 		return readMatrixFromHDFS(prop);
 	}
 	
@@ -193,14 +190,11 @@ public class DataConverter
 	{	
 		//Timing time = new Timing(true);
 		
-		long estnnz = (prop.expectedSparsity <= 0 || prop.rlen <= 0 || prop.clen <= 0) ? 
-			-1 : (long)(prop.expectedSparsity*prop.rlen*prop.clen);
-	
 		//core matrix reading 
 		MatrixBlock ret = null;
 		try {
 			MatrixReader reader = MatrixReaderFactory.createMatrixReader(prop);
-			ret = reader.readMatrixFromHDFS(prop.path, prop.rlen, prop.clen, prop.brlen, prop.bclen, estnnz);
+			ret = reader.readMatrixFromHDFS(prop.path, prop.rlen, prop.clen, prop.brlen, prop.bclen, prop.expectedNnz);
 		}
 		catch(DMLRuntimeException rex)
 		{

http://git-wip-us.apache.org/repos/asf/systemml/blob/e8774a7a/src/test/java/org/apache/sysml/test/integration/functions/caching/CachingPWriteExportTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/sysml/test/integration/functions/caching/CachingPWriteExportTest.java b/src/test/java/org/apache/sysml/test/integration/functions/caching/CachingPWriteExportTest.java
index 201d32a..8e45674 100644
--- a/src/test/java/org/apache/sysml/test/integration/functions/caching/CachingPWriteExportTest.java
+++ b/src/test/java/org/apache/sysml/test/integration/functions/caching/CachingPWriteExportTest.java
@@ -60,27 +60,21 @@ public class CachingPWriteExportTest extends AutomatedTestBase
 	}
 	
 	
-	/**
-	 * 
-	 * @param outer execution mode of outer parfor loop
-	 * @param inner execution mode of inner parfor loop
-	 * @param instType execution mode of instructions
-	 */
 	private void runTestExport( String outputFormat )
-	{				
+	{
 		TestConfiguration config = getTestConfiguration(TEST_NAME);
 		config.addVariable("rows", rows);
 		config.addVariable("cols", cols);
 		loadTestConfiguration(config);
 		
-		/* This is for running the junit test the new way, i.e., construct the arguments directly */
 		String HOME = SCRIPT_DIR + TEST_DIR;
 		fullDMLScriptName = HOME + TEST_NAME + ".dml";
 		programArgs = new String[]{"-args", input("V"),
 			Integer.toString(rows), Integer.toString(cols), output("V"), outputFormat };
 
 		long seed = System.nanoTime();
-        double[][] V = getRandomMatrix(rows, cols, 0, 1, sparsity, seed);
+		long nnz = (long)Math.round(sparsity * rows * cols);
+		double[][] V = getRandomMatrix(rows, cols, 0, 1, sparsity, seed);
 		writeInputMatrix("V", V, true); //always text
 		writeExpectedMatrix("V", V);
 		
@@ -96,7 +90,8 @@ public class CachingPWriteExportTest extends AutomatedTestBase
 			else
 				ii = InputInfo.TextCellInputInfo;
 			
-			MatrixBlock mb = DataConverter.readMatrixFromHDFS(output("V"), ii, rows, cols, OptimizerUtils.DEFAULT_BLOCKSIZE, OptimizerUtils.DEFAULT_BLOCKSIZE, sparsity);
+			MatrixBlock mb = DataConverter.readMatrixFromHDFS(output("V"),
+				ii, rows, cols, OptimizerUtils.DEFAULT_BLOCKSIZE, OptimizerUtils.DEFAULT_BLOCKSIZE, nnz);
 			Vp = DataConverter.convertToDoubleMatrix(mb);
 		}
 		catch(Exception ex)

http://git-wip-us.apache.org/repos/asf/systemml/blob/e8774a7a/src/test/java/org/apache/sysml/test/integration/functions/data/FullStringInitializeTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/sysml/test/integration/functions/data/FullStringInitializeTest.java b/src/test/java/org/apache/sysml/test/integration/functions/data/FullStringInitializeTest.java
index 78e4021..095b11f 100644
--- a/src/test/java/org/apache/sysml/test/integration/functions/data/FullStringInitializeTest.java
+++ b/src/test/java/org/apache/sysml/test/integration/functions/data/FullStringInitializeTest.java
@@ -324,6 +324,7 @@ public class FullStringInitializeTest extends AutomatedTestBase
 			int cols = (intype==InputType.COL_VECTOR) ? 1 : colsMatrix;
 			int rows = (intype==InputType.ROW_VECTOR) ? 1 : rowsMatrix;
 			double sparsity = (sparse) ? spSparse : spDense;
+			long nnz = (long)Math.round(sparsity * rows * cols);
 			
 			//generate data
 			double[][] A = getRandomMatrix(rows, cols, -5, 5, sparsity, 7); 
@@ -362,7 +363,7 @@ public class FullStringInitializeTest extends AutomatedTestBase
 			if( !expectExcept ) {
 				//compare matrices 
 				MatrixBlock ret = DataConverter.readMatrixFromHDFS(output("A"), InputInfo.TextCellInputInfo,
-						rows, cols, OptimizerUtils.DEFAULT_BLOCKSIZE, OptimizerUtils.DEFAULT_BLOCKSIZE, sparsity, null);
+					rows, cols, OptimizerUtils.DEFAULT_BLOCKSIZE, OptimizerUtils.DEFAULT_BLOCKSIZE, nnz, null);
 				double[][] dret = DataConverter.convertToDoubleMatrix(ret);
 				TestUtils.compareMatrices(A, dret, rows, cols, eps);
 			}


[2/3] systemml git commit: [MINOR] Avoid unnecessary stats maintenance in spark remote parfor

Posted by mb...@apache.org.
[MINOR] Avoid unnecessary stats maintenance in spark remote parfor

This patch makes a minor performance improvement to spark remote parfor
jobs. In contrast to the MR backend, we don't propagate individual
statistics back to the driver via counters. Therefore, we now disable
statistics maintenance in remote parfor workers in case of spark which
reduces overhead for parfor loops with lots of fine-grained operations
(where stats maintenance can become a bottleneck).


Project: http://git-wip-us.apache.org/repos/asf/systemml/repo
Commit: http://git-wip-us.apache.org/repos/asf/systemml/commit/d34d6a62
Tree: http://git-wip-us.apache.org/repos/asf/systemml/tree/d34d6a62
Diff: http://git-wip-us.apache.org/repos/asf/systemml/diff/d34d6a62

Branch: refs/heads/master
Commit: d34d6a6299b56766f3a92a6cfee258fe8272545a
Parents: e8774a7
Author: Matthias Boehm <mb...@gmail.com>
Authored: Sun Apr 22 16:32:49 2018 -0700
Committer: Matthias Boehm <mb...@gmail.com>
Committed: Sun Apr 22 16:32:49 2018 -0700

----------------------------------------------------------------------
 .../controlprogram/parfor/ProgramConverter.java     |  8 ++++++--
 .../parfor/RemoteDPParForSparkWorker.java           | 16 +++++-----------
 .../parfor/RemoteParForSparkWorker.java             | 11 +++--------
 3 files changed, 14 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/systemml/blob/d34d6a62/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/ProgramConverter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/ProgramConverter.java b/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/ProgramConverter.java
index 1356634..919b357 100644
--- a/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/ProgramConverter.java
+++ b/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/ProgramConverter.java
@@ -1254,8 +1254,11 @@ public class ProgramConverter
 	////////////////////////////////
 	// PARSING 
 	////////////////////////////////
-
 	public static ParForBody parseParForBody( String in, int id ) {
+		return parseParForBody(in, id, false);
+	}
+	
+	public static ParForBody parseParForBody( String in, int id, boolean inSpark ) {
 		ParForBody body = new ParForBody();
 		
 		//header elimination
@@ -1284,7 +1287,8 @@ public class ProgramConverter
 		
 		//handle additional configs
 		String aconfs = st.nextToken();
-		parseAndSetAdditionalConfigurations( aconfs );
+		if( !inSpark )
+			parseAndSetAdditionalConfigurations( aconfs );
 		
 		//handle program
 		String progStr = st.nextToken();

http://git-wip-us.apache.org/repos/asf/systemml/blob/d34d6a62/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/RemoteDPParForSparkWorker.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/RemoteDPParForSparkWorker.java b/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/RemoteDPParForSparkWorker.java
index 4ab90ae..885b2b7 100644
--- a/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/RemoteDPParForSparkWorker.java
+++ b/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/RemoteDPParForSparkWorker.java
@@ -20,7 +20,6 @@
 package org.apache.sysml.runtime.controlprogram.parfor;
 
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -98,8 +97,6 @@ public class RemoteDPParForSparkWorker extends ParWorker implements PairFlatMapF
 	public Iterator<Tuple2<Long, String>> call(Iterator<Tuple2<Long, Iterable<Writable>>> arg0)
 		throws Exception 
 	{
-		ArrayList<Tuple2<Long,String>> ret = new ArrayList<>();
-		
 		//lazy parworker initialization
 		configureWorker( TaskContext.get().taskAttemptId() );
 	
@@ -132,12 +129,9 @@ public class RemoteDPParForSparkWorker extends ParWorker implements PairFlatMapF
 			_aIters.add( (int)(getExecutedIterations()-numIter) );
 		}
 		
-		//write output if required (matrix indexed write) 
-		ArrayList<String> tmp = RemoteParForUtils.exportResultVariables( _workerID, _ec.getVariables(), _resultVars );
-		for( String val : tmp )
-			ret.add(new Tuple2<>(_workerID, val));
-		
-		return ret.iterator();
+		//write output if required (matrix indexed write)
+		return RemoteParForUtils.exportResultVariables(_workerID, _ec.getVariables(), _resultVars)
+			.stream().map(s -> new Tuple2<>(_workerID, s)).iterator();
 	}
 
 	private void configureWorker( long ID ) 
@@ -150,7 +144,7 @@ public class RemoteDPParForSparkWorker extends ParWorker implements PairFlatMapF
 			CodegenUtils.getClassSync(e.getKey(), e.getValue());
 	
 		//parse and setup parfor body program
-		ParForBody body = ProgramConverter.parseParForBody(_prog, (int)_workerID);
+		ParForBody body = ProgramConverter.parseParForBody(_prog, (int)_workerID, true);
 		_childBlocks = body.getChildBlocks();
 		_ec          = body.getEc();
 		_resultVars  = body.getResultVariables();
@@ -171,7 +165,7 @@ public class RemoteDPParForSparkWorker extends ParWorker implements PairFlatMapF
 						CacheableData.cacheEvictionLocalFilePrefix +"_" + _workerID; 
 				//register entire working dir for delete on shutdown
 				RemoteParForUtils.cleanupWorkingDirectoriesOnShutdown();
-			}	
+			}
 		}
 		
 		//ensure that resultvar files are not removed

http://git-wip-us.apache.org/repos/asf/systemml/blob/d34d6a62/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/RemoteParForSparkWorker.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/RemoteParForSparkWorker.java b/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/RemoteParForSparkWorker.java
index 45e3bc7..7485602 100644
--- a/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/RemoteParForSparkWorker.java
+++ b/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/RemoteParForSparkWorker.java
@@ -20,7 +20,6 @@
 package org.apache.sysml.runtime.controlprogram.parfor;
 
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -83,12 +82,8 @@ public class RemoteParForSparkWorker extends ParWorker implements PairFlatMapFun
 		
 		//write output if required (matrix indexed write) 
 		//note: this copy is necessary for environments without spark libraries
-		ArrayList<Tuple2<Long,String>> ret = new ArrayList<>();
-		ArrayList<String> tmp = RemoteParForUtils.exportResultVariables( _workerID, _ec.getVariables(), _resultVars );
-		for( String val : tmp )
-			ret.add(new Tuple2<>(_workerID, val));
-		
-		return ret.iterator();
+		return RemoteParForUtils.exportResultVariables(_workerID, _ec.getVariables(), _resultVars)
+			.stream().map(s -> new Tuple2<>(_workerID, s)).iterator();
 	}
 	
 	private void configureWorker(long taskID) 
@@ -101,7 +96,7 @@ public class RemoteParForSparkWorker extends ParWorker implements PairFlatMapFun
 			CodegenUtils.getClassSync(e.getKey(), e.getValue());
 	
 		//parse and setup parfor body program
-		ParForBody body = ProgramConverter.parseParForBody(_prog, (int)_workerID);
+		ParForBody body = ProgramConverter.parseParForBody(_prog, (int)_workerID, true);
 		_childBlocks = body.getChildBlocks();
 		_ec          = body.getEc();
 		_resultVars  = body.getResultVariables();


[3/3] systemml git commit: [SYSTEMML-2276] Avoid unnecessary read of empty binary matrices

Posted by mb...@apache.org.
[SYSTEMML-2276] Avoid unnecessary read of empty binary matrices

So far all matrices where read independent of the given number of
non-zeros. For empty, and sparse matrices in general, we allocate a
subset of sparse rows as synchronization pointers. This patch modifies
the binary block readers to early out for known empty matrices and
immediately return a non-allocated matrix block instead. This is
especially helpful for remote parfor loops where empty result variables
are read by all parfor tasks and thus are partially contented on the
shared common thread pool.
 

Project: http://git-wip-us.apache.org/repos/asf/systemml/repo
Commit: http://git-wip-us.apache.org/repos/asf/systemml/commit/728b2c90
Tree: http://git-wip-us.apache.org/repos/asf/systemml/tree/728b2c90
Diff: http://git-wip-us.apache.org/repos/asf/systemml/diff/728b2c90

Branch: refs/heads/master
Commit: 728b2c904abf7f98042a78eba497bd79ebe6dea9
Parents: d34d6a6
Author: Matthias Boehm <mb...@gmail.com>
Authored: Sun Apr 22 16:47:13 2018 -0700
Committer: Matthias Boehm <mb...@gmail.com>
Committed: Sun Apr 22 16:47:13 2018 -0700

----------------------------------------------------------------------
 src/main/java/org/apache/sysml/runtime/io/MatrixReader.java    | 1 +
 .../java/org/apache/sysml/runtime/io/ReaderBinaryBlock.java    | 4 ++++
 .../org/apache/sysml/runtime/io/ReaderBinaryBlockParallel.java | 6 +++++-
 3 files changed, 10 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/systemml/blob/728b2c90/src/main/java/org/apache/sysml/runtime/io/MatrixReader.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/io/MatrixReader.java b/src/main/java/org/apache/sysml/runtime/io/MatrixReader.java
index f9df756..3109065 100644
--- a/src/main/java/org/apache/sysml/runtime/io/MatrixReader.java
+++ b/src/main/java/org/apache/sysml/runtime/io/MatrixReader.java
@@ -49,6 +49,7 @@ public abstract class MatrixReader
 {
 	//internal configuration
 	protected static final boolean AGGREGATE_BLOCK_NNZ = true;
+	protected static final boolean RETURN_EMPTY_NNZ0 = true;
 	
 	public abstract MatrixBlock readMatrixFromHDFS( String fname, long rlen, long clen, int brlen, int bclen, long estnnz )
 		throws IOException, DMLRuntimeException;

http://git-wip-us.apache.org/repos/asf/systemml/blob/728b2c90/src/main/java/org/apache/sysml/runtime/io/ReaderBinaryBlock.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/io/ReaderBinaryBlock.java b/src/main/java/org/apache/sysml/runtime/io/ReaderBinaryBlock.java
index a0c1ca3..9461ca1 100644
--- a/src/main/java/org/apache/sysml/runtime/io/ReaderBinaryBlock.java
+++ b/src/main/java/org/apache/sysml/runtime/io/ReaderBinaryBlock.java
@@ -54,6 +54,10 @@ public class ReaderBinaryBlock extends MatrixReader
 	public MatrixBlock readMatrixFromHDFS(String fname, long rlen, long clen, int brlen, int bclen, long estnnz) 
 		throws IOException, DMLRuntimeException 
 	{
+		//early abort for known empty matrices (e.g., remote parfor result vars)
+		if( RETURN_EMPTY_NNZ0 && estnnz == 0 )
+			return new MatrixBlock((int)rlen, (int)clen, true);
+		
 		//allocate output matrix block
 		MatrixBlock ret = createOutputMatrixBlock(rlen, clen, brlen, bclen, estnnz, false, false);
 		

http://git-wip-us.apache.org/repos/asf/systemml/blob/728b2c90/src/main/java/org/apache/sysml/runtime/io/ReaderBinaryBlockParallel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/io/ReaderBinaryBlockParallel.java b/src/main/java/org/apache/sysml/runtime/io/ReaderBinaryBlockParallel.java
index 70e6e21..871abd7 100644
--- a/src/main/java/org/apache/sysml/runtime/io/ReaderBinaryBlockParallel.java
+++ b/src/main/java/org/apache/sysml/runtime/io/ReaderBinaryBlockParallel.java
@@ -54,7 +54,11 @@ public class ReaderBinaryBlockParallel extends ReaderBinaryBlock
 	@Override
 	public MatrixBlock readMatrixFromHDFS(String fname, long rlen, long clen, int brlen, int bclen, long estnnz) 
 		throws IOException, DMLRuntimeException 
-	{	
+	{
+		//early abort for known empty matrices (e.g., remote parfor result vars)
+		if( RETURN_EMPTY_NNZ0 && estnnz == 0 )
+			return new MatrixBlock((int)rlen, (int)clen, true);
+		
 		//allocate output matrix block (incl block allocation for parallel)
 		MatrixBlock ret = createOutputMatrixBlock(rlen, clen, brlen, bclen, estnnz, true, true);