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/19 08:16:59 UTC

[1/3] systemml git commit: [SYSTEMML-2255] Improved heuristics for calls to native BLAS libraries

Repository: systemml
Updated Branches:
  refs/heads/master d1bf80ac5 -> 09b1533de


[SYSTEMML-2255] Improved heuristics for calls to native BLAS libraries

This patch fine-tunes the heuristics for deciding upon forwarding
classes of matrix multiplications to native BLAS libraries. So far we
excluded matrix-vector multiplications because these are usually
memory-bandwidth-bound. However, on modern processors with wide SIMD
registers and fused-multiply-add, this is counter productive in certain
cases. We now extended the heuristics by allowing native BLAS calls for
matrix-vector with the input sizes fit into typical L3 cache sizes.


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

Branch: refs/heads/master
Commit: 02e5ba5649b23470bb6fc1726604badde5f5da8e
Parents: d1bf80a
Author: Matthias Boehm <mb...@gmail.com>
Authored: Wed Apr 18 17:38:48 2018 -0700
Committer: Matthias Boehm <mb...@gmail.com>
Committed: Wed Apr 18 21:40:15 2018 -0700

----------------------------------------------------------------------
 .../java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java | 3 ++-
 .../org/apache/sysml/runtime/matrix/data/LibMatrixNative.java    | 4 +++-
 2 files changed, 5 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/systemml/blob/02e5ba56/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java
index 91adc93..d9e741a 100644
--- a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java
+++ b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java
@@ -59,7 +59,8 @@ public class LibMatrixMult
 	private static final long MEM_OVERHEAD_THRESHOLD = 2L*1024*1024; //MAX 2 MB
 	private static final long PAR_MINFLOP_THRESHOLD1 = 2L*1024*1024; //MIN 2 MFLOP
 	private static final long PAR_MINFLOP_THRESHOLD2 = 128L*1024; //MIN 2 MFLOP
-	private static final int L2_CACHESIZE = 256 *1024; //256KB (common size)
+	public static final int L2_CACHESIZE = 256 * 1024; //256KB (common size)
+	public static final int L3_CACHESIZE = 16 * 1024 * 1024; //16MB (common size)
 	
 	private LibMatrixMult() {
 		//prevent instantiation via private constructor

http://git-wip-us.apache.org/repos/asf/systemml/blob/02e5ba56/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixNative.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixNative.java b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixNative.java
index c0922da..1d46927 100644
--- a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixNative.java
+++ b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixNative.java
@@ -49,7 +49,9 @@ public class LibMatrixNative
 	// We could encapsulate heuristics in this function
 	// For now, we only consider matrix-vector operation to be memory bound
 	private static boolean isMatMultMemoryBound(int m1Rlen, int m1Clen, int m2Clen) {
-		return m1Rlen == 1 || m1Clen == 1 || m2Clen == 1;
+		return (m1Rlen == 1 || m1Clen == 1 || m2Clen == 1)
+			&& (8L*m1Rlen*m1Clen > 16 * LibMatrixMult.L3_CACHESIZE 
+				|| 8L*m1Clen*m2Clen > 16 * LibMatrixMult.L3_CACHESIZE);
 	}
 
 	/**


[3/3] systemml git commit: [SYSTEMML-2258] Fix thread contention on acquire shared parfor input

Posted by mb...@apache.org.
[SYSTEMML-2258] Fix thread contention on acquire shared parfor input

This patch shortens the critical sections of the acquireRead and release
primitives (for buffer pool objects). We now maintain the pinned status
and statistics outside the synchronized block, which improves
unnecessary contention on acquiring shared reads in local parfor loops
with large degree of parallelism. 

As a positive side effect of maintaining the statistics outside the
synchronized block, the -stats output now clearly shows such contention
issues because the waiting time for the lock is counted into the acquire
read time.


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

Branch: refs/heads/master
Commit: 09b1533de71da735ecb86a4d331a0fd1eba0f30f
Parents: f6e3a91
Author: Matthias Boehm <mb...@gmail.com>
Authored: Thu Apr 19 01:17:39 2018 -0700
Committer: Matthias Boehm <mb...@gmail.com>
Committed: Thu Apr 19 01:17:39 2018 -0700

----------------------------------------------------------------------
 .../controlprogram/caching/CacheableData.java   | 119 ++++++++++---------
 1 file changed, 62 insertions(+), 57 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/systemml/blob/09b1533d/src/main/java/org/apache/sysml/runtime/controlprogram/caching/CacheableData.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/controlprogram/caching/CacheableData.java b/src/main/java/org/apache/sysml/runtime/controlprogram/caching/CacheableData.java
index 1ba6c4c..6e63284 100644
--- a/src/main/java/org/apache/sysml/runtime/controlprogram/caching/CacheableData.java
+++ b/src/main/java/org/apache/sysml/runtime/controlprogram/caching/CacheableData.java
@@ -370,37 +370,52 @@ public abstract class CacheableData<T extends CacheBlock> extends Data
 	 * 
 	 * @return cacheable data
 	 */
-	public synchronized T acquireRead()
-	{
-		if( LOG.isTraceEnabled() )
-			LOG.trace("Acquire read "+hashCode());
+	public T acquireRead() {
 		long t0 = DMLScript.STATISTICS ? System.nanoTime() : 0;
 		
+		//core internal acquire (synchronized per object)
+		T ret = acquireReadIntern();
+		
+		//update thread-local status (after pin but outside the
+		//critical section of accessing a shared object)
+		if( !isBelowCachingThreshold() )
+			updateStatusPinned(true);
+		
+		if( DMLScript.STATISTICS ){
+			long t1 = System.nanoTime();
+			CacheStatistics.incrementAcquireRTime(t1-t0);
+		}
+		
+		return ret;
+	}
+	
+	private synchronized T acquireReadIntern() {
 		if ( !isAvailableToRead() )
 			throw new DMLRuntimeException("MatrixObject not available to read.");
 		
 		//get object from cache
 		if( _data == null )
 			getCache();
-			
+		
 		//call acquireHostRead if gpuHandle is set as well as is allocated
-        boolean copiedFromGPU = false;
-        for (Map.Entry<GPUContext, GPUObject> kv : _gpuObjects.entrySet()) {
-            GPUObject gObj = kv.getValue();
-            if (gObj != null && copiedFromGPU && gObj.isDirty()) {
-                LOG.error("Inconsistent internal state - A copy of this CacheableData was dirty on more than 1 GPU");
-                throw new DMLRuntimeException("Internal Error : Inconsistent internal state, A copy of this CacheableData was dirty on more than 1 GPU");
-            } else if (gObj != null){
-                copiedFromGPU = gObj.acquireHostRead(null);
-                if( _data == null )
-                    getCache();
-            }
-        }
+		if( DMLScript.USE_ACCELERATOR ) {
+			boolean copiedFromGPU = false;
+			for (Map.Entry<GPUContext, GPUObject> kv : _gpuObjects.entrySet()) {
+				GPUObject gObj = kv.getValue();
+				if (gObj != null && copiedFromGPU && gObj.isDirty())
+					throw new DMLRuntimeException("Internal Error : Inconsistent internal state, A copy of this CacheableData was dirty on more than 1 GPU");
+				else if (gObj != null) {
+					copiedFromGPU = gObj.acquireHostRead(null);
+					if( _data == null )
+						getCache();
+				}
+			}
+		}
 
 		//read data from HDFS/RDD if required
-		//(probe data for cache_nowrite / jvm_reuse)  
-		if( isEmpty(true) && _data==null ) 
-		{			
+		//(probe data for cache_nowrite / jvm_reuse)
+		if( isEmpty(true) && _data==null )
+		{
 			try
 			{
 				if( DMLScript.STATISTICS )
@@ -437,21 +452,13 @@ public abstract class CacheableData<T extends CacheBlock> extends Data
 			
 			_isAcquireFromEmpty = true;
 		}
-		else if( DMLScript.STATISTICS )
-		{
+		else if( DMLScript.STATISTICS ) {
 			if( _data!=null )
 				CacheStatistics.incrementMemHits();
 		}
 		
 		//cache status maintenance
 		acquire( false, _data==null );
-		updateStatusPinned(true);
-		
-		if( DMLScript.STATISTICS ){
-			long t1 = System.nanoTime();
-			CacheStatistics.incrementAcquireRTime(t1-t0);
-		}
-		
 		return _data;
 	}
 
@@ -467,8 +474,8 @@ public abstract class CacheableData<T extends CacheBlock> extends Data
 	 */
 	public synchronized T acquireModify() 
 	{
-		if( LOG.isTraceEnabled() )
-			LOG.trace("Acquire modify "+hashCode());
+		//TODO remove after debugger (as only consumer) has been removed, because
+		//recent features such as gpu data transfers are not yet integrated
 		long t0 = DMLScript.STATISTICS ? System.nanoTime() : 0;
 		
 		if ( !isAvailableToModify() )
@@ -526,8 +533,6 @@ public abstract class CacheableData<T extends CacheBlock> extends Data
 	 */
 	public synchronized T acquireModify(T newData, String opcode)
 	{
-		if( LOG.isTraceEnabled() )
-			LOG.trace("Acquire modify newdata "+hashCode());
 		long t0 = DMLScript.STATISTICS ? System.nanoTime() : 0;
 		
 		if (! isAvailableToModify ())
@@ -546,7 +551,8 @@ public abstract class CacheableData<T extends CacheBlock> extends Data
 		if (newData == null)
 			throw new DMLRuntimeException("acquireModify with empty cache block.");
 		_data = newData;
-		updateStatusPinned(true);
+		if( !isBelowCachingThreshold() )
+			updateStatusPinned(true);
 		
 		if( DMLScript.STATISTICS ){
 			long t1 = System.nanoTime();
@@ -580,15 +586,27 @@ public abstract class CacheableData<T extends CacheBlock> extends Data
 	 * Out-Status: READ(-1), EVICTABLE, EMPTY.
 	 * 
 	 */
-	public synchronized void release(String opcode) 
-	{
-		if( LOG.isTraceEnabled() )
-			LOG.trace("Release "+hashCode());
+	public void release(String opcode) {
 		long t0 = DMLScript.STATISTICS ? System.nanoTime() : 0;
 		
+		//update thread-local status (before unpin but outside
+		//the critical section of accessing a shared object)
+		if( !isBelowCachingThreshold() )
+			updateStatusPinned(false);
+		
+		//core internal release (synchronized per object)
+		releaseIntern(opcode);
+		
+		if( DMLScript.STATISTICS ){
+			long t1 = System.nanoTime();
+			CacheStatistics.incrementReleaseTime(t1-t0);
+		}
+	}
+	
+	private synchronized void releaseIntern(String opcode)
+	{
 		boolean write = false;
-		if ( isModify() )
-		{
+		if ( isModify() ) {
 			//set flags for write
 			write = true;
 			setDirty(true);
@@ -602,14 +620,12 @@ public abstract class CacheableData<T extends CacheBlock> extends Data
 		
 		//cache status maintenance (pass cacheNoWrite flag)
 		release(_isAcquireFromEmpty && !_requiresLocalWrite);
-		updateStatusPinned(false);
 		
-		if(    isCachingActive() //only if caching is enabled (otherwise keep everything in mem)
-			&& isCached(true)    //not empty and not read/modify
+		if( isCachingActive() //only if caching is enabled (otherwise keep everything in mem)
+			&& isCached(true) //not empty and not read/modify
 			&& !isBelowCachingThreshold() ) //min size for caching
 		{
-			if( write || _requiresLocalWrite ) 
-			{
+			if( write || _requiresLocalWrite ) {
 				//evict blob
 				String filePath = getCacheFilePathAndName();
 				try {
@@ -632,14 +648,6 @@ public abstract class CacheableData<T extends CacheBlock> extends Data
 			createCache();
 			_data = null;
 		}
-		else if( LOG.isTraceEnabled() ){
-			LOG.trace("Var "+hashCode()+" not subject to caching, state="+getStatusAsString());
-		}
-
-		if( DMLScript.STATISTICS ){
-			long t1 = System.nanoTime();
-			CacheStatistics.incrementReleaseTime(t1-t0);
-		}
 	}
 	
 	/**
@@ -653,9 +661,6 @@ public abstract class CacheableData<T extends CacheBlock> extends Data
 	 */
 	public synchronized void clearData() 
 	{
-		if( LOG.isTraceEnabled() )
-			LOG.trace("Clear data "+hashCode());
-		
 		// check if cleanup enabled and possible 
 		if( !isCleanupEnabled() ) 
 			return; // do nothing
@@ -1201,7 +1206,7 @@ public abstract class CacheableData<T extends CacheBlock> extends Data
 	 * referenced cache block.  
 	 */
 	protected void createCache( ) {
-		_cache = new SoftReference<>( _data );	
+		_cache = new SoftReference<>( _data );
 	}
 
 	/**


[2/3] systemml git commit: [SYSTEMML-2256] Exploit native matrix mult in dense wsigmoid

Posted by mb...@apache.org.
[SYSTEMML-2256] Exploit native matrix mult in dense wsigmoid 

This patch improves the performance of the fused dense wsigmoid on
modern processors with wide SIMD registers and fma by exploiting a
native matrix mult as part of the larger wsigmod computation.


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

Branch: refs/heads/master
Commit: f6e3a91dfe8852839be6b471ba0eabc723f55bf1
Parents: 02e5ba5
Author: Matthias Boehm <mb...@gmail.com>
Authored: Wed Apr 18 21:26:01 2018 -0700
Committer: Matthias Boehm <mb...@gmail.com>
Committed: Wed Apr 18 21:40:17 2018 -0700

----------------------------------------------------------------------
 .../runtime/matrix/data/LibMatrixMult.java      | 43 +++++++++++++++++++-
 .../runtime/matrix/data/LibMatrixNative.java    |  2 +-
 2 files changed, 43 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/systemml/blob/f6e3a91d/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java
index d9e741a..3a2c58e 100644
--- a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java
+++ b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixMult.java
@@ -42,6 +42,7 @@ import org.apache.sysml.runtime.functionobjects.ValueFunction;
 import org.apache.sysml.runtime.matrix.operators.ReorgOperator;
 import org.apache.sysml.runtime.util.CommonThreadPool;
 import org.apache.sysml.runtime.util.UtilFunctions;
+import org.apache.sysml.utils.NativeHelper;
 
 /**
  * MB: Library for matrix multiplications including MM, MV, VV for all
@@ -557,7 +558,13 @@ public class LibMatrixMult
 		ret.allocateBlock();
 		
 		//core weighted square sum mm computation
-		if( !mW.sparse && !mU.sparse && !mV.sparse && !mU.isEmptyBlock() && !mV.isEmptyBlock() )
+		boolean allDense = !mW.sparse && !mU.sparse && !mV.sparse
+			&& !mU.isEmptyBlock() && !mV.isEmptyBlock();
+		if( NativeHelper.isNativeLibraryLoaded() && allDense && (mW.rlen == 1 || mW.clen == 1) 
+			&& !LibMatrixNative.isMatMultMemoryBound(mU.rlen, mU.clen, mV.rlen)
+			&& mW.getDenseBlock().isContiguous() && mU.getDenseBlock().isContiguous() && mV.getDenseBlock().isContiguous() )
+			matrixMultWSigmoidDenseNative(mW, mU, mV, ret, wt);
+		else if( allDense )
 			matrixMultWSigmoidDense(mW, mU, mV, ret, wt, 0, mW.rlen);
 		else if( mW.sparse && !mU.sparse && !mV.sparse && !mU.isEmptyBlock() && !mV.isEmptyBlock())
 			matrixMultWSigmoidSparseDense(mW, mU, mV, ret, wt, 0, mW.rlen);
@@ -2384,6 +2391,30 @@ public class LibMatrixMult
 			dotProduct(tmp1.getDenseBlockValues(), tmp2.getDenseBlockValues(), mU.clen*mU.clen)));
 	}
 
+	private static void matrixMultWSigmoidDenseNative(MatrixBlock mW, MatrixBlock mU, MatrixBlock mV, MatrixBlock ret, WSigmoidType wt) {
+		double[] w = mW.getDenseBlockValues();
+		double[] c = ret.getDenseBlockValues();
+		final int m = mW.rlen, n = mW.clen;
+		final int cd = mU.clen;
+		boolean flagminus = (wt==WSigmoidType.MINUS || wt==WSigmoidType.LOG_MINUS); 
+		boolean flaglog = (wt==WSigmoidType.LOG || wt==WSigmoidType.LOG_MINUS);
+		
+		//call native matrix multiplication (only called for single-threaded and matrix-vector
+		//because this ensures that we can deal with the transpose mV without additional transpose)
+		if(!NativeHelper.dmmdd(((m==1)?mV:mU).getDenseBlockValues(),
+			((m==1)?mU:mV).getDenseBlockValues(), c, (m==1)?n:m, cd, 1, 1) )
+			throw new DMLRuntimeException("Error executing native matrix mult.");
+		
+		//compute remaining wsigmoid for all relevant outputs
+		for(int i=0, ix=0; i<m; i++, ix+=n) {
+			for(int j=0; j<n; j++) {
+				double wij = w[ix +j];
+				//if( wij != 0 )
+					c[ix+j] = wsigmoid(wij, c[ix+j], flagminus, flaglog);
+			}
+		}
+	}
+	
 	private static void matrixMultWSigmoidDense(MatrixBlock mW, MatrixBlock mU, MatrixBlock mV, MatrixBlock ret, WSigmoidType wt, int rl, int ru) {
 		DenseBlock w = mW.getDenseBlock();
 		DenseBlock c = ret.getDenseBlock();
@@ -3462,6 +3493,16 @@ public class LibMatrixMult
 		//compute weighted output
 		return wij * ((flaglog) ? Math.log(cval) : cval);
 	}
+	
+	private static double wsigmoid(final double wij, final double uvij, final boolean flagminus, final boolean flaglog) {
+		//compute core sigmoid function
+		double cval = flagminus ?
+				1 / (1 + FastMath.exp(uvij)) :
+				1 / (1 + FastMath.exp(-uvij));
+		
+		//compute weighted output
+		return wij * ((flaglog) ? Math.log(cval) : cval);
+	}
 
 	private static void wdivmm( final double wij, double[] u, double[] v, double[] c, final int uix, final int vix, final boolean left, final boolean mult, final boolean minus, final int len )
 	{

http://git-wip-us.apache.org/repos/asf/systemml/blob/f6e3a91d/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixNative.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixNative.java b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixNative.java
index 1d46927..eade43f 100644
--- a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixNative.java
+++ b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixNative.java
@@ -48,7 +48,7 @@ public class LibMatrixNative
 	
 	// We could encapsulate heuristics in this function
 	// For now, we only consider matrix-vector operation to be memory bound
-	private static boolean isMatMultMemoryBound(int m1Rlen, int m1Clen, int m2Clen) {
+	public static boolean isMatMultMemoryBound(int m1Rlen, int m1Clen, int m2Clen) {
 		return (m1Rlen == 1 || m1Clen == 1 || m2Clen == 1)
 			&& (8L*m1Rlen*m1Clen > 16 * LibMatrixMult.L3_CACHESIZE 
 				|| 8L*m1Clen*m2Clen > 16 * LibMatrixMult.L3_CACHESIZE);