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/20 08:46:06 UTC
[7/7] systemml git commit: [SYSTEMML-2262] New multi-threaded dense
unary ops (exp, log, sigmoid)
[SYSTEMML-2262] New multi-threaded dense unary ops (exp, log, sigmoid)
This patch introduces a best effort multi-threading for expensive dense
unary operations such as exp, log, and sigmoid. While for other unary
operations, the output allocation, read and write anyway dominate, these
operations experience a substantial speedup with multi-threading, which
we simply apply via a parallelSetAll.
Project: http://git-wip-us.apache.org/repos/asf/systemml/repo
Commit: http://git-wip-us.apache.org/repos/asf/systemml/commit/4c7640b8
Tree: http://git-wip-us.apache.org/repos/asf/systemml/tree/4c7640b8
Diff: http://git-wip-us.apache.org/repos/asf/systemml/diff/4c7640b8
Branch: refs/heads/master
Commit: 4c7640b873dfa921409cbef375c856aa48940932
Parents: 45d86bd
Author: Matthias Boehm <mb...@gmail.com>
Authored: Fri Apr 20 01:39:15 2018 -0700
Committer: Matthias Boehm <mb...@gmail.com>
Committed: Fri Apr 20 01:39:15 2018 -0700
----------------------------------------------------------------------
.../org/apache/sysml/hops/OptimizerUtils.java | 16 ++++-----
.../java/org/apache/sysml/hops/UnaryOp.java | 36 ++++++++++++--------
src/main/java/org/apache/sysml/lops/Unary.java | 9 +++--
.../parfor/opt/OptimizerRuleBased.java | 3 +-
.../instructions/CPInstructionParser.java | 4 ++-
.../instructions/cp/UnaryCPInstruction.java | 2 +-
.../sysml/runtime/matrix/data/MatrixBlock.java | 17 ++++++---
7 files changed, 54 insertions(+), 33 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/systemml/blob/4c7640b8/src/main/java/org/apache/sysml/hops/OptimizerUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/OptimizerUtils.java b/src/main/java/org/apache/sysml/hops/OptimizerUtils.java
index 5ae20eb..2d76759 100644
--- a/src/main/java/org/apache/sysml/hops/OptimizerUtils.java
+++ b/src/main/java/org/apache/sysml/hops/OptimizerUtils.java
@@ -414,30 +414,30 @@ public class OptimizerUtils
*
* @return local memory budget
*/
- public static double getLocalMemBudget()
- {
+ public static double getLocalMemBudget() {
double ret = InfrastructureAnalyzer.getLocalMaxMemory();
return ret * OptimizerUtils.MEM_UTIL_FACTOR;
}
- public static double getRemoteMemBudgetMap()
- {
+ public static double getRemoteMemBudgetMap() {
return getRemoteMemBudgetMap(false);
}
- public static double getRemoteMemBudgetMap(boolean substractSortBuffer)
- {
+ public static double getRemoteMemBudgetMap(boolean substractSortBuffer) {
double ret = InfrastructureAnalyzer.getRemoteMaxMemoryMap();
if( substractSortBuffer )
ret -= InfrastructureAnalyzer.getRemoteMaxMemorySortBuffer();
return ret * OptimizerUtils.MEM_UTIL_FACTOR;
}
- public static double getRemoteMemBudgetReduce()
- {
+ public static double getRemoteMemBudgetReduce() {
double ret = InfrastructureAnalyzer.getRemoteMaxMemoryReduce();
return ret * OptimizerUtils.MEM_UTIL_FACTOR;
}
+
+ public static boolean isMaxLocalParallelism(int k) {
+ return InfrastructureAnalyzer.getLocalParallelism() == k;
+ }
public static boolean checkSparkBroadcastMemoryBudget( double size )
{
http://git-wip-us.apache.org/repos/asf/systemml/blob/4c7640b8/src/main/java/org/apache/sysml/hops/UnaryOp.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/UnaryOp.java b/src/main/java/org/apache/sysml/hops/UnaryOp.java
index a6a9d66..7b7c685 100644
--- a/src/main/java/org/apache/sysml/hops/UnaryOp.java
+++ b/src/main/java/org/apache/sysml/hops/UnaryOp.java
@@ -177,9 +177,10 @@ public class UnaryOp extends Hop implements MultiThreadedHop
}
else //default unary
{
- int k = isCumulativeUnaryOperation() ? OptimizerUtils.getConstrainedNumThreads( _maxNumThreads ) : 1;
- Unary unary1 = new Unary(input.constructLops(), HopsOpOp1LopsU.get(_op),
- getDataType(), getValueType(), et, k);
+ int k = isCumulativeUnaryOperation() || isExpensiveUnaryOperation() ?
+ OptimizerUtils.getConstrainedNumThreads( _maxNumThreads ) : 1;
+ Unary unary1 = new Unary(input.constructLops(),
+ HopsOpOp1LopsU.get(_op), getDataType(), getValueType(), et, k);
setOutputDimensions(unary1);
setLineNumbers(unary1);
setLops(unary1);
@@ -612,21 +613,26 @@ public class UnaryOp extends Hop implements MultiThreadedHop
return ( _op == OpOp1.INVERSE );
}
- public boolean isCumulativeUnaryOperation()
- {
- return ( _op == OpOp1.CUMSUM
- || _op == OpOp1.CUMPROD
- || _op == OpOp1.CUMMIN
- || _op == OpOp1.CUMMAX );
+ public boolean isCumulativeUnaryOperation() {
+ return (_op == OpOp1.CUMSUM
+ || _op == OpOp1.CUMPROD
+ || _op == OpOp1.CUMMIN
+ || _op == OpOp1.CUMMAX);
}
public boolean isCastUnaryOperation() {
- return ( _op == OpOp1.CAST_AS_MATRIX
- || _op == OpOp1.CAST_AS_SCALAR
- || _op == OpOp1.CAST_AS_FRAME
- || _op == OpOp1.CAST_AS_BOOLEAN
- || _op == OpOp1.CAST_AS_DOUBLE
- || _op == OpOp1.CAST_AS_INT );
+ return (_op == OpOp1.CAST_AS_MATRIX
+ || _op == OpOp1.CAST_AS_SCALAR
+ || _op == OpOp1.CAST_AS_FRAME
+ || _op == OpOp1.CAST_AS_BOOLEAN
+ || _op == OpOp1.CAST_AS_DOUBLE
+ || _op == OpOp1.CAST_AS_INT);
+ }
+
+ public boolean isExpensiveUnaryOperation() {
+ return (_op == OpOp1.EXP
+ || _op == OpOp1.LOG
+ || _op == OpOp1.SIGMOID);
}
@Override
http://git-wip-us.apache.org/repos/asf/systemml/blob/4c7640b8/src/main/java/org/apache/sysml/lops/Unary.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/lops/Unary.java b/src/main/java/org/apache/sysml/lops/Unary.java
index 7c1ceeb..a5403b2 100644
--- a/src/main/java/org/apache/sysml/lops/Unary.java
+++ b/src/main/java/org/apache/sysml/lops/Unary.java
@@ -325,11 +325,14 @@ public class Unary extends Lop
}
}
- public static boolean isCumulativeOp(OperationTypes op) {
+ public static boolean isMultiThreadedOp(OperationTypes op) {
return op==OperationTypes.CUMSUM
|| op==OperationTypes.CUMPROD
|| op==OperationTypes.CUMMIN
- || op==OperationTypes.CUMMAX;
+ || op==OperationTypes.CUMMAX
+ || op==OperationTypes.EXP
+ || op==OperationTypes.LOG
+ || op==OperationTypes.SIGMOID;
}
@Override
@@ -351,7 +354,7 @@ public class Unary extends Lop
sb.append( prepOutputOperand(output) );
//num threads for cumulative cp ops
- if( getExecType() == ExecType.CP && isCumulativeOp(operation) ) {
+ if( getExecType() == ExecType.CP && isMultiThreadedOp(operation) ) {
sb.append( OPERAND_DELIMITOR );
sb.append( _numThreads );
}
http://git-wip-us.apache.org/repos/asf/systemml/blob/4c7640b8/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/opt/OptimizerRuleBased.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/opt/OptimizerRuleBased.java b/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/opt/OptimizerRuleBased.java
index e13f2a7..a7f5834 100644
--- a/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/opt/OptimizerRuleBased.java
+++ b/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/opt/OptimizerRuleBased.java
@@ -1317,7 +1317,8 @@ public class OptimizerRuleBased extends Optimizer
&& !HopRewriteUtils.isValidOp(((ParameterizedBuiltinOp)h).getOp(),
ParamBuiltinOp.GROUPEDAGG, ParamBuiltinOp.REXPAND))
&& !( h instanceof UnaryOp //only unaryop-cumulativeagg
- && !((UnaryOp)h).isCumulativeUnaryOperation() )
+ && !((UnaryOp)h).isCumulativeUnaryOperation()
+ && !((UnaryOp)h).isExpensiveUnaryOperation())
&& !( h instanceof ReorgOp //only reorgop-transpose
&& ((ReorgOp)h).getOp() != ReOrgOp.TRANS ))
{
http://git-wip-us.apache.org/repos/asf/systemml/blob/4c7640b8/src/main/java/org/apache/sysml/runtime/instructions/CPInstructionParser.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/instructions/CPInstructionParser.java b/src/main/java/org/apache/sysml/runtime/instructions/CPInstructionParser.java
index 9dbb24e..395a4ec 100644
--- a/src/main/java/org/apache/sysml/runtime/instructions/CPInstructionParser.java
+++ b/src/main/java/org/apache/sysml/runtime/instructions/CPInstructionParser.java
@@ -64,6 +64,7 @@ import org.apache.sysml.runtime.instructions.cp.UaggOuterChainCPInstruction;
import org.apache.sysml.runtime.instructions.cp.UnaryCPInstruction;
import org.apache.sysml.runtime.instructions.cp.VariableCPInstruction;
import org.apache.sysml.runtime.instructions.cpfile.MatrixIndexingCPFileInstruction;
+import org.apache.sysml.runtime.util.UtilFunctions;
public class CPInstructionParser extends InstructionParser
{
@@ -385,7 +386,8 @@ public class CPInstructionParser extends InstructionParser
case Builtin:
String []parts = InstructionUtils.getInstructionPartsWithValueType(str);
if ( parts[0].equals("log") || parts[0].equals("log_nz") ) {
- if ( parts.length == 3 ) {
+ if ( parts.length == 3 || (parts.length == 4 &&
+ UtilFunctions.isIntegerNumber(parts[3])) ) {
// B=log(A), y=log(x)
return UnaryCPInstruction.parseInstruction(str);
} else if ( parts.length == 4 ) {
http://git-wip-us.apache.org/repos/asf/systemml/blob/4c7640b8/src/main/java/org/apache/sysml/runtime/instructions/cp/UnaryCPInstruction.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/instructions/cp/UnaryCPInstruction.java b/src/main/java/org/apache/sysml/runtime/instructions/cp/UnaryCPInstruction.java
index 07be2a7..8e023ea 100644
--- a/src/main/java/org/apache/sysml/runtime/instructions/cp/UnaryCPInstruction.java
+++ b/src/main/java/org/apache/sysml/runtime/instructions/cp/UnaryCPInstruction.java
@@ -62,7 +62,7 @@ public abstract class UnaryCPInstruction extends ComputationCPInstruction {
out.split(parts[2]);
func = Builtin.getBuiltinFnObject(opcode);
- if( Arrays.asList(new String[]{"ucumk+","ucum*","ucummin","ucummax"}).contains(opcode) )
+ if( Arrays.asList(new String[]{"ucumk+","ucum*","ucummin","ucummax","exp","log","sigmoid"}).contains(opcode) )
return new UnaryMatrixCPInstruction(new UnaryOperator(func,Integer.parseInt(parts[3])), in, out, opcode, str);
else
return new UnaryScalarCPInstruction(null, in, out, opcode, str);
http://git-wip-us.apache.org/repos/asf/systemml/blob/4c7640b8/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 f738227..bb5e79b 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
@@ -2577,16 +2577,25 @@ public class MatrixBlock extends MatrixValue implements CacheBlock, Externalizab
ret.reset(rlen, clen, sp);
//core execute
- if( LibMatrixAgg.isSupportedUnaryOperator(op) )
- {
+ if( LibMatrixAgg.isSupportedUnaryOperator(op) ) {
//e.g., cumsum/cumprod/cummin/cumax
if( op.getNumThreads() > 1 )
LibMatrixAgg.cumaggregateUnaryMatrix(this, ret, op, op.getNumThreads());
else
LibMatrixAgg.cumaggregateUnaryMatrix(this, ret, op);
}
- else
- {
+ else if(!sparse && !isEmptyBlock(false) && getDenseBlock().isContiguous()
+ && OptimizerUtils.isMaxLocalParallelism(op.getNumThreads())) {
+ //note: we apply multi-threading in a best-effort manner here
+ //only for expensive operators such as exp, log, sigmoid, because
+ //otherwise allocation, read and write anyway dominates
+ ret.allocateDenseBlock(false);
+ double[] a = getDenseBlockValues();
+ double[] c = ret.getDenseBlockValues();
+ Arrays.parallelSetAll(c, i -> op.fn.execute(a[i]));
+ ret.recomputeNonZeros();
+ }
+ else {
//default execute unary operations
if(op.sparseSafe)
sparseUnaryOperations(op, ret);