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 2017/11/05 22:29:55 UTC
[3/3] systemml git commit: [SYSTEMML-1988] JMLC API extension for
cloning prepared scripts
[SYSTEMML-1988] JMLC API extension for cloning prepared scripts
In complex applications and micro services, the need to reuse prepared
scripts in a thread-local manner in order to amortize the compilation
overhead, creates sometimes an unnecessary burden. Without dynamic
recompilation, this is unnecessary because a single compiled program can
be shared across concurrent invocations of PreparedScript.execute. This
patch extends the JMLC API by cloning functionality, which allows to
statically initialize a single prepared script and create cheap shallow
copies of the script's program and meta data.
Project: http://git-wip-us.apache.org/repos/asf/systemml/repo
Commit: http://git-wip-us.apache.org/repos/asf/systemml/commit/f7fe4342
Tree: http://git-wip-us.apache.org/repos/asf/systemml/tree/f7fe4342
Diff: http://git-wip-us.apache.org/repos/asf/systemml/diff/f7fe4342
Branch: refs/heads/master
Commit: f7fe4342005ec0da383f359b70fbab48a25dff7a
Parents: e888cce
Author: Matthias Boehm <mb...@gmail.com>
Authored: Sat Nov 4 23:33:43 2017 -0700
Committer: Matthias Boehm <mb...@gmail.com>
Committed: Sun Nov 5 14:27:44 2017 -0800
----------------------------------------------------------------------
.../org/apache/sysml/api/jmlc/Connection.java | 15 +++
.../apache/sysml/api/jmlc/PreparedScript.java | 37 ++++++
.../jmlc/JMLCClonedPreparedScriptTest.java | 113 +++++++++++++++++++
.../functions/jmlc/ZPackageSuite.java | 2 +
4 files changed, 167 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/systemml/blob/f7fe4342/src/main/java/org/apache/sysml/api/jmlc/Connection.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/api/jmlc/Connection.java b/src/main/java/org/apache/sysml/api/jmlc/Connection.java
index e96e0aa..2568977 100644
--- a/src/main/java/org/apache/sysml/api/jmlc/Connection.java
+++ b/src/main/java/org/apache/sysml/api/jmlc/Connection.java
@@ -161,6 +161,21 @@ public class Connection implements Closeable
* @param script string representing the DML or PyDML script
* @param inputs string array of input variables to register
* @param outputs string array of output variables to register
+ * @return PreparedScript object representing the precompiled script
+ * @throws DMLException if DMLException occurs
+ */
+ public PreparedScript prepareScript( String script, String[] inputs, String[] outputs)
+ throws DMLException
+ {
+ return prepareScript(script, inputs, outputs, false);
+ }
+
+ /**
+ * Prepares (precompiles) a script and registers input and output variables.
+ *
+ * @param script string representing the DML or PyDML script
+ * @param inputs string array of input variables to register
+ * @param outputs string array of output variables to register
* @param parsePyDML {@code true} if PyDML, {@code false} if DML
* @return PreparedScript object representing the precompiled script
* @throws DMLException if DMLException occurs
http://git-wip-us.apache.org/repos/asf/systemml/blob/f7fe4342/src/main/java/org/apache/sysml/api/jmlc/PreparedScript.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/api/jmlc/PreparedScript.java b/src/main/java/org/apache/sysml/api/jmlc/PreparedScript.java
index c712bb2..c23ef92 100644
--- a/src/main/java/org/apache/sysml/api/jmlc/PreparedScript.java
+++ b/src/main/java/org/apache/sysml/api/jmlc/PreparedScript.java
@@ -23,7 +23,9 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map.Entry;
+import org.apache.commons.lang.NotImplementedException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.sysml.api.DMLException;
@@ -75,6 +77,21 @@ public class PreparedScript
private final DMLConfig _dmlconf;
private final CompilerConfig _cconf;
+ private PreparedScript(PreparedScript that) {
+ //shallow copy, except for a separate symbol table
+ //and related meta data of reused inputs
+ _prog = that._prog;
+ _vars = new LocalVariableMap();
+ for(Entry<String, Data> e : that._vars.entrySet())
+ _vars.put(e.getKey(), e.getValue());
+ _vars.setRegisteredOutputs(that._outVarnames);
+ _inVarnames = that._inVarnames;
+ _outVarnames = that._outVarnames;
+ _inVarReuse = new HashMap<>(that._inVarReuse);
+ _dmlconf = that._dmlconf;
+ _cconf = that._cconf;
+ }
+
/**
* Meant to be invoked only from Connection.
*
@@ -481,4 +498,24 @@ public class PreparedScript
}
}
}
+
+ /**
+ * Creates a cloned instance of the prepared script, which
+ * allows for concurrent execution without side effects.
+ *
+ * @param deep indicator if a deep copy needs to be created;
+ * if false, only a shallow (i.e., by reference) copy of the
+ * program and read-only meta data is created.
+ * @return an equivalent prepared script
+ */
+ public PreparedScript clone(boolean deep) {
+ if( deep )
+ throw new NotImplementedException();
+ return new PreparedScript(this);
+ }
+
+ @Override
+ public Object clone() {
+ return clone(true);
+ }
}
http://git-wip-us.apache.org/repos/asf/systemml/blob/f7fe4342/src/test/java/org/apache/sysml/test/integration/functions/jmlc/JMLCClonedPreparedScriptTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/sysml/test/integration/functions/jmlc/JMLCClonedPreparedScriptTest.java b/src/test/java/org/apache/sysml/test/integration/functions/jmlc/JMLCClonedPreparedScriptTest.java
new file mode 100644
index 0000000..d0667e0
--- /dev/null
+++ b/src/test/java/org/apache/sysml/test/integration/functions/jmlc/JMLCClonedPreparedScriptTest.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sysml.test.integration.functions.jmlc;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.sysml.api.DMLException;
+import org.apache.sysml.api.DMLScript;
+import org.apache.sysml.api.jmlc.Connection;
+import org.apache.sysml.api.jmlc.PreparedScript;
+import org.apache.sysml.runtime.controlprogram.parfor.stat.InfrastructureAnalyzer;
+import org.apache.sysml.test.integration.AutomatedTestBase;
+import org.apache.sysml.utils.Statistics;
+
+public class JMLCClonedPreparedScriptTest extends AutomatedTestBase
+{
+ @Override
+ public void setUp() {
+ //do nothing
+ }
+
+ @Test
+ public void testSinglePreparedScript128() throws IOException {
+ runJMLCClonedTest(128, false);
+ }
+
+ @Test
+ public void testClonedPreparedScript128() throws IOException {
+ runJMLCClonedTest(128, true);
+ }
+
+ private void runJMLCClonedTest(int num, boolean clone)
+ throws IOException
+ {
+ int k = InfrastructureAnalyzer.getLocalParallelism();
+
+ boolean failed = false;
+ try( Connection conn = new Connection() ) {
+ String script =
+ " X = matrix(7, 10, 10);"
+ + "R = matrix(0, 10, 1)"
+ + "parfor(i in 1:nrow(X))"
+ + " R[i,] = sum(X[i,])"
+ + "out = sum(R)"
+ + "write(out, 'tmp/out')";
+ DMLScript.STATISTICS = true;
+ Statistics.reset();
+ PreparedScript pscript = conn.prepareScript(
+ script, new String[]{}, new String[]{"out"}, false);
+
+ ExecutorService pool = Executors.newFixedThreadPool(k);
+ ArrayList<JMLCTask> tasks = new ArrayList<>();
+ for(int i=0; i<num; i++)
+ tasks.add(new JMLCTask(pscript, clone));
+ List<Future<Double>> taskrets = pool.invokeAll(tasks);
+ for(Future<Double> ret : taskrets)
+ if( ret.get() != 700 )
+ throw new RuntimeException("wrong results: "+ret.get());
+ pool.shutdown();
+ }
+ catch(Exception ex) {
+ failed = true;
+ }
+
+ //check expected failure
+ Assert.assertTrue(failed==!clone || k==1);
+ }
+
+ private static class JMLCTask implements Callable<Double>
+ {
+ private final PreparedScript _pscript;
+ private final boolean _clone;
+
+ protected JMLCTask(PreparedScript pscript, boolean clone) {
+ _pscript = pscript;
+ _clone = clone;
+ }
+
+ @Override
+ public Double call() throws DMLException
+ {
+ if( _clone )
+ return _pscript.clone(false).executeScript().getDouble("out");
+ else
+ return _pscript.executeScript().getDouble("out");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/systemml/blob/f7fe4342/src/test_suites/java/org/apache/sysml/test/integration/functions/jmlc/ZPackageSuite.java
----------------------------------------------------------------------
diff --git a/src/test_suites/java/org/apache/sysml/test/integration/functions/jmlc/ZPackageSuite.java b/src/test_suites/java/org/apache/sysml/test/integration/functions/jmlc/ZPackageSuite.java
index 3d5c13a..05fa8bc 100644
--- a/src/test_suites/java/org/apache/sysml/test/integration/functions/jmlc/ZPackageSuite.java
+++ b/src/test_suites/java/org/apache/sysml/test/integration/functions/jmlc/ZPackageSuite.java
@@ -34,8 +34,10 @@ import org.junit.runners.Suite;
FrameLeftIndexingTest.class,
FrameReadMetaTest.class,
FrameTransformTest.class,
+ JMLCClonedPreparedScriptTest.class,
JMLCInputOutputTest.class,
JMLCInputStreamReadTest.class,
+ JMLCParfor2ForCompileTest.class,
ReuseModelVariablesTest.class,
MulticlassSVMScoreTest.class
})