Repository: systemml Updated Branches: refs/heads/master 352c256a3 -> 8de008d21
[SYSTEMML-1757] New optional selective function recompile through JMLC This patch extends the JMLC prepared script by functionality for selective function recompilation. By default prepared scripts are compiled without size information which renders a lot of rewrites inapplicable and dynamic recompilation is disabled. With selective function recompile users can mark important functions for dynamic recompilation without introducing the overhead for full-fledged dynamic recompilation, which can outweigh the benefits of dynamic recompilation on small data. Project: http://git-wip-us.apache.org/repos/asf/systemml/repo Commit: http://git-wip-us.apache.org/repos/asf/systemml/commit/8de008d2 Tree: http://git-wip-us.apache.org/repos/asf/systemml/tree/8de008d2 Diff: http://git-wip-us.apache.org/repos/asf/systemml/diff/8de008d2 Branch: refs/heads/master Commit: 8de008d21e51cf6feede0a298392fcb11a3d22da Parents: 352c256 Author: Matthias Boehm <[email protected]> Authored: Mon Jul 10 22:49:00 2017 -0700 Committer: Matthias Boehm <[email protected]> Committed: Mon Jul 10 22:49:27 2017 -0700 ---------------------------------------------------------------------- .../apache/sysml/api/jmlc/PreparedScript.java | 55 ++++++++++++++++++++ .../ipa/IPAPassFlagFunctionsRecompileOnce.java | 4 ++ 2 files changed, 59 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/systemml/blob/8de008d2/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 5e0c879..d9f5992 100644 --- a/src/main/java/org/apache/sysml/api/jmlc/PreparedScript.java +++ b/src/main/java/org/apache/sysml/api/jmlc/PreparedScript.java @@ -27,10 +27,17 @@ import java.util.HashSet; import java.util.List; import java.util.Map.Entry; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.sysml.api.DMLException; +import org.apache.sysml.conf.CompilerConfig; import org.apache.sysml.conf.ConfigurationManager; +import org.apache.sysml.conf.CompilerConfig.ConfigType; import org.apache.sysml.hops.OptimizerUtils; +import org.apache.sysml.hops.ipa.FunctionCallGraph; +import org.apache.sysml.parser.DMLProgram; import org.apache.sysml.parser.Expression.ValueType; +import org.apache.sysml.runtime.controlprogram.FunctionProgramBlock; import org.apache.sysml.runtime.controlprogram.LocalVariableMap; import org.apache.sysml.runtime.controlprogram.Program; import org.apache.sysml.runtime.controlprogram.caching.FrameObject; @@ -57,6 +64,8 @@ import org.apache.sysml.utils.Explain; */ public class PreparedScript { + private static final Log LOG = LogFactory.getLog(PreparedScript.class.getName()); + //input/output specification private HashSet<String> _inVarnames = null; private HashSet<String> _outVarnames = null; @@ -412,4 +421,50 @@ public class PreparedScript public String explain() throws DMLException { return Explain.explain(_prog); } + + /** + * Enables function recompilation, selectively for the given functions. + * If dynamic recompilation is globally enabled this has no additional + * effect; otherwise the given functions are dynamically recompiled once + * on every entry but not at the granularity of individually last-level + * program blocks. Use this fine-grained recompilation option for important + * functions in small-data scenarios where dynamic recompilation overheads + * might not be amortized. + * + * @param fnamespace function namespace, null for default namespace + * @param fnames function name + * @throws DMLException if any compilation error occurs + */ + public void enableFunctionRecompile(String fnamespace, String... fnames) + throws DMLException + { + //handle default name space + if( fnamespace == null ) + fnamespace = DMLProgram.DEFAULT_NAMESPACE; + + //enable dynamic recompilation (note that this does not globally enable + //dynamic recompilation because the program has been compiled already) + CompilerConfig cconf = ConfigurationManager.getCompilerConfig(); + cconf.set(ConfigType.ALLOW_DYN_RECOMPILATION, true); + ConfigurationManager.setLocalConfig(cconf); + + //build function call graph (to probe for recursive functions) + FunctionCallGraph fgraph = _prog.getProgramBlocks().isEmpty() ? null : + new FunctionCallGraph(_prog.getProgramBlocks().get(0).getStatementBlock().getDMLProg()); + + //enable requested functions for recompile once + for( String fname : fnames ) { + String fkey = DMLProgram.constructFunctionKey(fnamespace, fname); + if( !fgraph.isRecursiveFunction(fkey) ) { + FunctionProgramBlock fpb = _prog.getFunctionProgramBlock(fnamespace, fname); + if( fpb != null ) + fpb.setRecompileOnce(true); + else + LOG.warn("Failed to enable function recompile for non-existing '"+fkey+"'."); + } + else { + LOG.warn("Failed to enable function recompile for recursive '"+fkey+"'."); + } + } + } } http://git-wip-us.apache.org/repos/asf/systemml/blob/8de008d2/src/main/java/org/apache/sysml/hops/ipa/IPAPassFlagFunctionsRecompileOnce.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/ipa/IPAPassFlagFunctionsRecompileOnce.java b/src/main/java/org/apache/sysml/hops/ipa/IPAPassFlagFunctionsRecompileOnce.java index 82f4681..314f0ed 100644 --- a/src/main/java/org/apache/sysml/hops/ipa/IPAPassFlagFunctionsRecompileOnce.java +++ b/src/main/java/org/apache/sysml/hops/ipa/IPAPassFlagFunctionsRecompileOnce.java @@ -19,6 +19,7 @@ package org.apache.sysml.hops.ipa; +import org.apache.sysml.conf.ConfigurationManager; import org.apache.sysml.hops.HopsException; import org.apache.sysml.parser.DMLProgram; import org.apache.sysml.parser.ForStatementBlock; @@ -51,6 +52,9 @@ public class IPAPassFlagFunctionsRecompileOnce extends IPAPass public void rewriteProgram( DMLProgram prog, FunctionCallGraph fgraph, FunctionCallSizeInfo fcallSizes ) throws HopsException { + if( !ConfigurationManager.isDynamicRecompilation() ) + return; + try { for (String namespaceKey : prog.getNamespaces().keySet()) for (String fname : prog.getFunctionStatementBlocks(namespaceKey).keySet())
