This is an automated email from the ASF dual-hosted git repository.

mboehm7 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/systemml.git


The following commit(s) were added to refs/heads/master by this push:
     new 6c94556  [SYSTEMDS-331] Extended lineage-based reuse (caching of 
scalars)
6c94556 is described below

commit 6c9455678b2c38a41db741270a86812b05ee77ca
Author: arnabp <[email protected]>
AuthorDate: Thu Apr 9 17:45:12 2020 +0200

    [SYSTEMDS-331] Extended lineage-based reuse (caching of scalars)
    
    - This patch contains lineage caching support for scalar objects. This
    enables instruction level and multi-level reuse of
    operations/functions/statementblocks producing at least one scalar
    output. This patch improves multi-level cache hits.
    - Furthermore, this adds a new option `-reuse_multilevel` to enable
    multi-level reuse.
    - This patch also fixes few bugs and enhances reusable instructions
    list.
    - Additional fix for lineage cache reset to avoid endless loops on
    eviction in sequences of tests
    
    Closes #876.
---
 docs/Tasks.txt                                     |  12 +
 src/main/java/org/apache/sysds/api/DMLOptions.java |   2 +
 .../runtime/controlprogram/BasicProgramBlock.java  |   5 +-
 .../runtime/instructions/cp/BooleanObject.java     |   5 +
 .../runtime/instructions/cp/DoubleObject.java      |   5 +
 .../sysds/runtime/instructions/cp/IntObject.java   |   5 +
 .../runtime/instructions/cp/ScalarObject.java      |   3 +
 .../runtime/instructions/cp/StringObject.java      |   5 +
 .../org/apache/sysds/runtime/lineage/Lineage.java  |   1 +
 .../apache/sysds/runtime/lineage/LineageCache.java | 255 ++++++++++++++-------
 .../sysds/runtime/lineage/LineageCacheConfig.java  |   8 +-
 .../runtime/lineage/LineageCacheStatistics.java    |   4 +-
 .../sysds/runtime/lineage/LineageCodegenItem.java  |   4 +
 .../apache/sysds/runtime/lineage/LineageMap.java   |   8 +-
 .../sysds/runtime/lineage/LineageParser.java       |   6 +-
 .../sysds/runtime/lineage/LineageRewriteReuse.java |  77 ++-----
 .../sysds/runtime/lineage/LineageTokenizer.java    |   2 +-
 .../test/functions/lineage/FullReuseTest.java      |   7 +
 .../functions/lineage/FunctionFullReuseTest.java   |   2 +-
 .../test/functions/lineage/SBFullReuseTest.java    |   2 +-
 src/test/scripts/functions/lineage/FullReuse4.dml  |  34 +++
 21 files changed, 296 insertions(+), 156 deletions(-)

diff --git a/docs/Tasks.txt b/docs/Tasks.txt
index 5fd6749..42741da 100644
--- a/docs/Tasks.txt
+++ b/docs/Tasks.txt
@@ -236,6 +236,18 @@ SYSTEMDS-320 Merge SystemDS into Apache SystemML           
           OK
  * 321 Merge histories of SystemDS and SystemML                       OK
  * 322 Change global package names                                    OK
  * 323 Fix licenses and notice file                                   OK 
+ 
+SYSTEMDS-330 Lineage Tracing, Reuse and Integration
+ * 331 Cache and reuse scalar outputs (instruction and multi-level)   OK
+ * 332 Parfor integration with multi-level reuse 
+ * 333 Use exact execution time for cost based eviction
+ 
+SYSTEMDS-340 Compiler Assisted Lineage Caching and Reuse
+ * 341 Finalize unmarking of loop dependent operations
+ * 342 Mark functions as last-use to enable early eviction
+ * 343 Identify equal last level HOPs to ensure SB-level reuse
+ * 344 Unmark functions/SBs containing non-determinism for caching
+ * 345 Compiler assisted cache configuration
 
 Others:
  * Break append instruction to cbind and rbind 
diff --git a/src/main/java/org/apache/sysds/api/DMLOptions.java 
b/src/main/java/org/apache/sysds/api/DMLOptions.java
index 7eca8ab..b9972a3 100644
--- a/src/main/java/org/apache/sysds/api/DMLOptions.java
+++ b/src/main/java/org/apache/sysds/api/DMLOptions.java
@@ -120,6 +120,8 @@ public class DMLOptions {
                                                        dmlOptions.linReuseType 
= ReuseCacheType.REUSE_FULL;
                                                else if 
(lineageType.equalsIgnoreCase("reuse_partial"))
                                                        dmlOptions.linReuseType 
= ReuseCacheType.REUSE_PARTIAL;
+                                               else if 
(lineageType.equalsIgnoreCase("reuse_multilevel"))
+                                                       dmlOptions.linReuseType 
= ReuseCacheType.REUSE_MULTILEVEL;
                                                else if 
(lineageType.equalsIgnoreCase("reuse_hybrid"))
                                                        dmlOptions.linReuseType 
= ReuseCacheType.REUSE_HYBRID;
                                                else if 
(lineageType.equalsIgnoreCase("none"))
diff --git 
a/src/main/java/org/apache/sysds/runtime/controlprogram/BasicProgramBlock.java 
b/src/main/java/org/apache/sysds/runtime/controlprogram/BasicProgramBlock.java
index 2a9e281..1f52a75 100644
--- 
a/src/main/java/org/apache/sysds/runtime/controlprogram/BasicProgramBlock.java
+++ 
b/src/main/java/org/apache/sysds/runtime/controlprogram/BasicProgramBlock.java
@@ -28,6 +28,7 @@ import org.apache.sysds.runtime.DMLRuntimeException;
 import org.apache.sysds.runtime.controlprogram.context.ExecutionContext;
 import org.apache.sysds.runtime.instructions.Instruction;
 import org.apache.sysds.runtime.lineage.LineageCache;
+import org.apache.sysds.runtime.lineage.LineageCacheConfig;
 import org.apache.sysds.runtime.lineage.LineageCacheConfig.ReuseCacheType;
 import org.apache.sysds.runtime.lineage.LineageCacheStatistics;
 import org.apache.sysds.runtime.lineage.LineageItem;
@@ -107,7 +108,9 @@ public class BasicProgramBlock extends ProgramBlock
                
                //statement-block-level, lineage-based reuse
                LineageItem[] liInputs = null;
-               if (_sb != null && !ReuseCacheType.isNone()) {
+               if (_sb != null 
+                       && !ReuseCacheType.isNone()
+                       && 
LineageCacheConfig.getCacheType().isMultilevelReuse()) {
                        String name = "SB" + _sb.getSBID();
                        liInputs = 
LineageItemUtils.getLineageItemInputstoSB(_sb.getInputstoSB(), ec);
                        if( LineageCache.reuse(_sb.getOutputsofSB(), 
_sb.getOutputsofSB().size(), liInputs, name, ec) ) {
diff --git 
a/src/main/java/org/apache/sysds/runtime/instructions/cp/BooleanObject.java 
b/src/main/java/org/apache/sysds/runtime/instructions/cp/BooleanObject.java
index 35f5705..c285761 100644
--- a/src/main/java/org/apache/sysds/runtime/instructions/cp/BooleanObject.java
+++ b/src/main/java/org/apache/sysds/runtime/instructions/cp/BooleanObject.java
@@ -62,4 +62,9 @@ public class BooleanObject extends ScalarObject
        public Object getValue(){
                return _value;
        }
+
+       @Override
+       public int getSize() {
+               return 16 + 8;
+       }
 }
diff --git 
a/src/main/java/org/apache/sysds/runtime/instructions/cp/DoubleObject.java 
b/src/main/java/org/apache/sysds/runtime/instructions/cp/DoubleObject.java
index 0fc0b9f..f7327ca 100644
--- a/src/main/java/org/apache/sysds/runtime/instructions/cp/DoubleObject.java
+++ b/src/main/java/org/apache/sysds/runtime/instructions/cp/DoubleObject.java
@@ -62,4 +62,9 @@ public class DoubleObject extends ScalarObject
        public String getDebugName() {
                return null;
        }
+       
+       @Override
+       public int getSize() {
+               return 16 + Double.SIZE/Byte.SIZE;
+       }
 }
diff --git 
a/src/main/java/org/apache/sysds/runtime/instructions/cp/IntObject.java 
b/src/main/java/org/apache/sysds/runtime/instructions/cp/IntObject.java
index 0d0a743..84a0934 100644
--- a/src/main/java/org/apache/sysds/runtime/instructions/cp/IntObject.java
+++ b/src/main/java/org/apache/sysds/runtime/instructions/cp/IntObject.java
@@ -58,4 +58,9 @@ public class IntObject extends ScalarObject
        public Object getValue(){
                return _value;
        }
+       
+       @Override
+       public int getSize() {
+               return 16 + Integer.SIZE/Byte.SIZE;
+       }
 }
diff --git 
a/src/main/java/org/apache/sysds/runtime/instructions/cp/ScalarObject.java 
b/src/main/java/org/apache/sysds/runtime/instructions/cp/ScalarObject.java
index e114b97..f91ac80 100644
--- a/src/main/java/org/apache/sysds/runtime/instructions/cp/ScalarObject.java
+++ b/src/main/java/org/apache/sysds/runtime/instructions/cp/ScalarObject.java
@@ -38,6 +38,9 @@ public abstract class ScalarObject extends Data
 
        public abstract String getStringValue();
        
+       //TODO: Get the actual sizes by using profilers (JOL/Instrumentation) 
and hardcode in here.
+       public abstract int getSize();
+       
        public String getLanguageSpecificStringValue() {
                return getStringValue();
        }
diff --git 
a/src/main/java/org/apache/sysds/runtime/instructions/cp/StringObject.java 
b/src/main/java/org/apache/sysds/runtime/instructions/cp/StringObject.java
index d5c01cc..00d0037 100644
--- a/src/main/java/org/apache/sysds/runtime/instructions/cp/StringObject.java
+++ b/src/main/java/org/apache/sysds/runtime/instructions/cp/StringObject.java
@@ -59,6 +59,11 @@ public class StringObject extends ScalarObject
        public Object getValue(){
                return _value;
        }
+       
+       @Override
+       public int getSize() {
+               return 16 + _value.length() * 1;
+       }
 
        public static void checkMaxStringLength( long len ) {
                if( len > MAX_STRING_SIZE ) {
diff --git a/src/main/java/org/apache/sysds/runtime/lineage/Lineage.java 
b/src/main/java/org/apache/sysds/runtime/lineage/Lineage.java
index 9e61981..2b2c45a 100644
--- a/src/main/java/org/apache/sysds/runtime/lineage/Lineage.java
+++ b/src/main/java/org/apache/sysds/runtime/lineage/Lineage.java
@@ -123,6 +123,7 @@ public class Lineage {
        public static void resetInternalState() {
                LineageItem.resetIDSequence();
                LineageCache.resetCache();
+               LineageCacheStatistics.reset();
        }
        
        public static void setLinReusePartial() {
diff --git a/src/main/java/org/apache/sysds/runtime/lineage/LineageCache.java 
b/src/main/java/org/apache/sysds/runtime/lineage/LineageCache.java
index 1e07522..789b9f7 100644
--- a/src/main/java/org/apache/sysds/runtime/lineage/LineageCache.java
+++ b/src/main/java/org/apache/sysds/runtime/lineage/LineageCache.java
@@ -31,7 +31,6 @@ import 
org.apache.sysds.runtime.controlprogram.context.ExecutionContext;
 import 
org.apache.sysds.runtime.controlprogram.parfor.stat.InfrastructureAnalyzer;
 import org.apache.sysds.runtime.instructions.CPInstructionParser;
 import org.apache.sysds.runtime.instructions.Instruction;
-import 
org.apache.sysds.runtime.instructions.cp.BinaryMatrixMatrixCPInstruction;
 import org.apache.sysds.runtime.instructions.cp.CPInstruction.CPType;
 import org.apache.sysds.runtime.instructions.cp.ComputationCPInstruction;
 import org.apache.sysds.runtime.instructions.cp.Data;
@@ -56,7 +55,7 @@ public class LineageCache {
        private static final Map<LineageItem, Entry> _cache = new HashMap<>();
        private static final Map<LineageItem, SpilledItem> _spillList = new 
HashMap<>();
        private static final HashSet<LineageItem> _removelist = new HashSet<>();
-       private static final double CACHE_FRAC = 0.05; // 5% of JVM mem
+       private static final double CACHE_FRAC = 0.05; // 5% of JVM heap size
        private static final long CACHE_LIMIT; //limit in bytes
        private static String outdir = null;
        private static long _cachesize = 0;
@@ -93,62 +92,62 @@ public class LineageCache {
                                //create a placeholder if no reuse to avoid 
redundancy
                                //(e.g., concurrent threads that try to start 
the computation)
                                if(!reuse && isMarkedForCaching(inst, ec))
-                                       putIntern(item, null, 0);
+                                       putIntern(item, null, null, 0);
                        }
                }
                
                return reuse;
        }
        
-       public static MatrixBlock reuse(LineageItem item) {
+       public static Entry reuse(LineageItem item) {
                if (ReuseCacheType.isNone())
                        return null;
 
-               MatrixBlock d = null;
+               Entry e = null;
                synchronized( _cache ) {
                        if (LineageCache.probe(item)) 
-                               d = LineageCache.get(item);
+                               e = LineageCache.get(item);
                        else
                                //create a placeholder if no reuse to avoid 
redundancy
                                //(e.g., concurrent threads that try to start 
the computation)
-                               putIntern(item, null, 0);
+                               putIntern(item, null, null, 0);
                                //FIXME: parfor - every thread gets different 
function names
                }
-               return d;
+               return e;
        }
        
        public static boolean reuse(List<String> outputs, int numOutputs, 
LineageItem[] liInputs, String name, ExecutionContext ec)
        {
-               if( ReuseCacheType.isNone() )
+               if( ReuseCacheType.isNone() || 
!LineageCacheConfig.getCacheType().isMultilevelReuse())
                        return false;
 
                boolean reuse = (numOutputs != 0);
+               HashMap<String, Data> funcOutputs = new HashMap<>();
+               HashMap<String, LineageItem> funcLIs = new HashMap<>();
                for (int i=0; i<numOutputs; i++) {
                        String opcode = name + String.valueOf(i+1);
                        LineageItem li = new LineageItem(outputs.get(i), 
opcode, liInputs);
-                       MatrixBlock cachedValue = LineageCache.reuse(li); 
+                       Entry cachedValue = LineageCache.reuse(li); 
                        //TODO: handling of recursive calls
                        
-                       if (cachedValue != null) {
+                       if (cachedValue != null && !cachedValue.isNullVal()) {
                                String boundVarName = outputs.get(i);
+                               Data boundValue = null;
                                //convert to matrix object
-                               MetaDataFormat md = new 
MetaDataFormat(cachedValue.getDataCharacteristics(), 
-                                               
OutputInfo.BinaryCellOutputInfo, InputInfo.BinaryCellInputInfo);
-                               MatrixObject boundValue = new 
MatrixObject(ValueType.FP64, boundVarName, md);
-                               boundValue.acquireModify(cachedValue);
-                               boundValue.release();
-
-                               //cleanup existing data bound to output 
variable name
-                               Data exdata = ec.removeVariable(boundVarName);
-                               if( exdata != boundValue)
-                                       ec.cleanupDataObject(exdata);
+                               if (cachedValue.isMatrixValue()) {
+                                       MetaDataFormat md = new 
MetaDataFormat(cachedValue.getMBValue().getDataCharacteristics(), 
+                                                       
OutputInfo.BinaryCellOutputInfo, InputInfo.BinaryCellInputInfo);
+                                       boundValue = new 
MatrixObject(ValueType.FP64, boundVarName, md);
+                                       
((MatrixObject)boundValue).acquireModify(cachedValue.getMBValue());
+                                       ((MatrixObject)boundValue).release();
+                               }
+                               else
+                                       boundValue = cachedValue.getSOValue();
 
-                               //add/replace data in symbol table
-                               ec.setVariable(boundVarName, boundValue);
+                               funcOutputs.put(boundVarName, boundValue);
                                
-                               // map original lineage of function return to 
the calling site
                                LineageItem orig = _cache.get(li)._origItem; 
//FIXME: synchronize
-                               ec.getLineage().set(boundVarName, orig);
+                               funcLIs.put(boundVarName, orig);
                        }
                        else {
                                // if one output cannot be reused, we need to 
execute the function
@@ -157,6 +156,19 @@ public class LineageCache {
                                reuse = false;
                        }
                }
+               
+               if (reuse) {
+                       funcOutputs.forEach((var, val) -> {
+                               //cleanup existing data bound to output 
variable name
+                               Data exdata = ec.removeVariable(var);
+                               if( exdata != val)
+                                       ec.cleanupDataObject(exdata);
+                               //add/replace data in symbol table
+                               ec.setVariable(var, val);
+                       });
+                       //map original lineage items return to the calling site
+                       funcLIs.forEach((var, li) -> ec.getLineage().set(var, 
li));
+               }
                return reuse;
        }
        
@@ -164,9 +176,10 @@ public class LineageCache {
        public static void put(Instruction inst, ExecutionContext ec) {
                if (inst instanceof ComputationCPInstruction && 
isReusable(inst, ec) ) {
                        LineageItem item = ((LineageTraceable) 
inst).getLineageItems(ec)[0];
+                       //This method is called only to put matrix value
                        MatrixObject mo = 
ec.getMatrixObject(((ComputationCPInstruction) inst).output);
                        synchronized( _cache ) {
-                               putIntern(item, mo.acquireReadAndRelease(), 
getRecomputeEstimate(inst, ec));
+                               putIntern(item, mo.acquireReadAndRelease(), 
null, getRecomputeEstimate(inst, ec));
                        }
                }
        }
@@ -177,14 +190,18 @@ public class LineageCache {
                if (inst instanceof ComputationCPInstruction && 
isReusable(inst, ec) ) {
                        if (!isMarkedForCaching(inst, ec)) return;
                        LineageItem item = ((LineageTraceable) 
inst).getLineageItems(ec)[0];
-                       MatrixObject mo = 
ec.getMatrixObject(((ComputationCPInstruction) inst).output);
-                       MatrixBlock value = mo.acquireReadAndRelease();
-                       _cache.get(item).setValue(value, 
getRecomputeEstimate(inst, ec)); //outside sync to prevent deadlocks
+                       //MatrixObject mo = 
ec.getMatrixObject(((ComputationCPInstruction) inst).output);
+                       Data data = ec.getVariable(((ComputationCPInstruction) 
inst).output);
+                       MatrixObject mo = data instanceof MatrixObject ? 
(MatrixObject)data : null;
+                       ScalarObject so = data instanceof ScalarObject ? 
(ScalarObject)data : null;
+                       MatrixBlock Mval = mo != null ? 
mo.acquireReadAndRelease() : null;
+                       _cache.get(item).setValue(Mval, so, 
getRecomputeEstimate(inst, ec)); //outside sync to prevent deadlocks
+                       long size = _cache.get(item).getSize();
                        
                        synchronized( _cache ) {
-                               if( !isBelowThreshold(value) ) 
-                                       makeSpace(value);
-                               updateSize(value, true);
+                               if( !isBelowThreshold(size) ) 
+                                       makeSpace(size);
+                               updateSize(size, true);
                        }
                }
        }
@@ -193,15 +210,20 @@ public class LineageCache {
                if (ReuseCacheType.isNone())
                        return;
                if (LineageCache.probe(probeItem)) {
-                       MatrixBlock value = LineageCache.get(probeItem);
+                       Entry oe = LineageCache.get(probeItem);
                        Entry e = _cache.get(item);
-                       e.setValue(value, 0); //TODO: compute estimate for 
function
+                       //TODO: compute estimate for function
+                       if (oe.isMatrixValue())
+                               e.setValue(oe.getMBValue(), null, 0); 
+                       else
+                               e.setValue(null, oe.getSOValue(), 0);
                        e._origItem = probeItem; 
 
+                       long size = oe.getSize();
                        synchronized( _cache ) {
-                               if(!isBelowThreshold(value)) 
-                                       makeSpace(value);
-                               updateSize(value, true);
+                               if(!isBelowThreshold(size)) 
+                                       makeSpace(size);
+                               updateSize(size, true);
                        }
                }
                else
@@ -211,7 +233,7 @@ public class LineageCache {
 
        public static void putValue(List<String> outputs, int numOutputs, 
LineageItem[] liInputs, String name, ExecutionContext ec)
        {
-               if( ReuseCacheType.isNone() )
+               if( ReuseCacheType.isNone() || 
!LineageCacheConfig.getCacheType().isMultilevelReuse())
                        return;
 
                HashMap<LineageItem, LineageItem> FuncLIMap = new HashMap<>();
@@ -221,13 +243,11 @@ public class LineageCache {
                        LineageItem li = new LineageItem(outputs.get(i), 
opcode, liInputs);
                        String boundVarName = outputs.get(i);
                        LineageItem boundLI = ec.getLineage().get(boundVarName);
-                       Data boundValue = ec.getVariable(boundVarName);
                        if (boundLI != null)
                                boundLI.resetVisitStatus();
                        if (boundLI == null 
                                || !LineageCache.probe(li)
-                               || LineageItemUtils.containsRandDataGen(new 
HashSet<>(Arrays.asList(liInputs)), boundLI)
-                               || boundValue instanceof ScalarObject) { 
//TODO: cache scalar objects
+                               || LineageItemUtils.containsRandDataGen(new 
HashSet<>(Arrays.asList(liInputs)), boundLI)) {
                                AllOutputsCacheable = false;
                        }
                        FuncLIMap.put(li, boundLI);
@@ -243,22 +263,23 @@ public class LineageCache {
                return;
        }
        
-       private static void putIntern(LineageItem key, MatrixBlock value, 
double compcost) {
+       private static void putIntern(LineageItem key, MatrixBlock Mval, 
ScalarObject Sval, double compcost) {
                if (_cache.containsKey(key))
                        //can come here if reuse_partial option is enabled
                        return; 
                        //throw new DMLRuntimeException("Redundant lineage 
caching detected: "+inst);
                
                // Create a new entry.
-               Entry newItem = new Entry(key, value, compcost);
+               Entry newItem = new Entry(key, Mval, Sval, compcost);
                
                // Make space by removing or spilling LRU entries.
-               if( value != null ) {
-                       if( value.getInMemorySize() > CACHE_LIMIT )
+               if( Mval != null || Sval != null ) {
+                       long size = newItem.getSize();
+                       if( size > CACHE_LIMIT )
                                return; //not applicable
-                       if( !isBelowThreshold(value) ) 
-                               makeSpace(value);
-                       updateSize(value, true);
+                       if( !isBelowThreshold(size) ) 
+                               makeSpace(size);
+                       updateSize(size, true);
                }
                
                // Place the entry at head position.
@@ -282,6 +303,9 @@ public class LineageCache {
                _spillList.clear();
                _head = null;
                _end = null;
+               // reset cache size, otherwise the cache clear leads to 
unusable 
+               // space which means evictions could run into endless loops
+               _cachesize = 0;
                if (DMLScript.STATISTICS)
                        _removelist.clear();
        }
@@ -289,14 +313,17 @@ public class LineageCache {
 
        private static boolean fullReuse (LineageItem item, 
ComputationCPInstruction inst, ExecutionContext ec) {
                if (LineageCache.probe(item)) {
-                       MatrixBlock d = LineageCache.get(item);
-                       ec.setMatrixOutput(inst.output.getName(), d);
+                       Entry e = LineageCache.get(item);
+                       if (e.isMatrixValue())
+                               ec.setMatrixOutput(inst.output.getName(), 
e.getMBValue());
+                       else
+                               ec.setScalarOutput(inst.output.getName(), 
e.getSOValue());
                        return true;
                }
                return false;
        }
        
-       protected static MatrixBlock get(LineageItem key) {
+       protected static Entry get(LineageItem key) {
                // This method is called only when entry is present either in 
cache or in local FS.
                if (_cache.containsKey(key)) {
                        // Read and put the entry at head.
@@ -305,7 +332,7 @@ public class LineageCache {
                        setHead(e);
                        if (DMLScript.STATISTICS)
                                LineageCacheStatistics.incrementMemHits();
-                       return e.getValue();
+                       return e;
                }
                else
                        return readFromLocalFS(key);
@@ -315,10 +342,13 @@ public class LineageCache {
                // TODO: Move this to the new class LineageCacheConfig and 
extend
                return inst.getOpcode().equalsIgnoreCase("tsmm")
                                || inst.getOpcode().equalsIgnoreCase("ba+*")
-                               || ((inst.getOpcode().equalsIgnoreCase("*") 
-                               || inst.getOpcode().equalsIgnoreCase("/")) &&
-                                       inst instanceof 
BinaryMatrixMatrixCPInstruction) //TODO support scalar
+                               || inst.getOpcode().equalsIgnoreCase("*") 
+                               || inst.getOpcode().equalsIgnoreCase("/")
+                               || inst.getOpcode().equalsIgnoreCase("+")
+                               || inst.getOpcode().equalsIgnoreCase("nrow")
+                               || inst.getOpcode().equalsIgnoreCase("ncol")
                                || 
inst.getOpcode().equalsIgnoreCase("rightIndex")
+                               || 
inst.getOpcode().equalsIgnoreCase("leftIndex")
                                || 
inst.getOpcode().equalsIgnoreCase("groupedagg")
                                || inst.getOpcode().equalsIgnoreCase("r'")
                                || (inst.getOpcode().equalsIgnoreCase("append") 
&& isVectorAppend(inst, ec))
@@ -339,42 +369,56 @@ public class LineageCache {
                if (!LineageCacheConfig.getCompAssRW())
                        return true;
 
-               MatrixObject mo = 
ec.getMatrixObject(((ComputationCPInstruction)inst).output);
-               //limit this to full reuse as partial reuse is applicable even 
for loop dependent operation
-               boolean marked = (LineageCacheConfig.getCacheType() == 
ReuseCacheType.REUSE_FULL  && !mo.isMarked()) ? false : true; 
-               return marked;
+               if (((ComputationCPInstruction)inst).output.isMatrix()) {
+                       MatrixObject mo = 
ec.getMatrixObject(((ComputationCPInstruction)inst).output);
+                       //limit this to full reuse as partial reuse is 
applicable even for loop dependent operation
+                       boolean marked = (LineageCacheConfig.getCacheType() == 
ReuseCacheType.REUSE_FULL  
+                                       && !mo.isMarked()) ? false : true; 
+                       return marked;
+               }
+               else
+                       return true;
        }
        
        //---------------- CACHE SPACE MANAGEMENT METHODS -----------------
        
-       private static boolean isBelowThreshold(MatrixBlock value) {
-               return ((value.getInMemorySize() + _cachesize) <= CACHE_LIMIT);
+       private static boolean isBelowThreshold(long spaceNeeded) {
+               return ((spaceNeeded + _cachesize) <= CACHE_LIMIT);
        }
        
-       private static void makeSpace(MatrixBlock value) {
-               double valSize = value.getInMemorySize();
+       private static void makeSpace(long spaceNeeded) {
                // cost based eviction
-               while ((valSize+_cachesize) > CACHE_LIMIT)
+               while ((spaceNeeded +_cachesize) > CACHE_LIMIT)
                {
                        if (_cache.get(_end._key).isNullVal()) {
-                               setEnd2Head(_end);  // Must be null function 
entry. Move to next.
+                               //Must be a null function/SB placeholder entry. 
This 
+                               //function is currently being executed. Skip 
and continue.
+                               setEnd2Head(_end);
                                continue;
                        }
-                               
-                       double reduction = 
_cache.get(_end._key).getValue().getInMemorySize();
-                       if (_cache.get(_end._key)._compEst > 
getDiskSpillEstimate() 
-                                       && LineageCacheConfig.isSetSpill())
-                               spillToLocalFS(); // If re-computation is more 
expensive, spill data to disk.
+                       
+                       double reduction = _cache.get(_end._key).getSize();
+                       if (_cache.get(_end._key).isMatrixValue()) { //spill 
matrix blocks only
+                               if (_cache.get(_end._key)._compEst > 
getDiskSpillEstimate() 
+                                               && 
LineageCacheConfig.isSetSpill())
+                                       spillToLocalFS(); // If re-computation 
is more expensive, spill data to disk.
+                       }
 
+                       if (_cache.get(_end._key)._compEst == 0) {
+                               //Must be a function/SB/scalar entry. Move to 
next.
+                               //FIXME: Remove this logic after implementing 
new eviction logic.
+                               setEnd2Head(_end);  
+                               continue;
+                       }
                        removeEntry(reduction);
                } 
        }
        
-       private static void updateSize(MatrixBlock value, boolean addspace) {
+       private static void updateSize(long space, boolean addspace) {
                if (addspace)
-                       _cachesize += value.getInMemorySize();
+                       _cachesize += space;
                else
-                       _cachesize -= value.getInMemorySize();
+                       _cachesize -= space;
        }
 
        //---------------- COSTING RELATED METHODS -----------------
@@ -382,7 +426,7 @@ public class LineageCache {
        private static double getDiskSpillEstimate() {
                // This includes sum of writing to and reading from disk
                long t0 = DMLScript.STATISTICS ? System.nanoTime() : 0;
-               MatrixBlock mb = _cache.get(_end._key).getValue();
+               MatrixBlock mb = _cache.get(_end._key).getMBValue();
                long r = mb.getNumRows();
                long c = mb.getNumColumns();
                long nnz = mb.getNonZeros();
@@ -395,6 +439,10 @@ public class LineageCache {
        }
        
        private static double getRecomputeEstimate(Instruction inst, 
ExecutionContext ec) {
+               if (!((ComputationCPInstruction)inst).output.isMatrix()
+                       || (((ComputationCPInstruction)inst).input1 != null && 
!((ComputationCPInstruction)inst).input1.isMatrix()))
+                       return 0; //this method will be deprecated. No need to 
support scalar
+
                long t0 = DMLScript.STATISTICS ? System.nanoTime() : 0;
                double nflops = 0;
                String instop= inst.getOpcode().contains("spoof") ? "spoof" : 
inst.getOpcode();
@@ -464,7 +512,7 @@ public class LineageCache {
                                long nnz1 = mo1.getNnz();
                                double s1 = OptimizerUtils.getSparsity(r1, c1, 
nnz1);
                                boolean lsparse = 
MatrixBlock.evalSparseFormatInMemory(r1, c1, nnz1);
-                               if 
(inst.getOpcode().equalsIgnoreCase("rightIndex"))
+                               //if 
(inst.getOpcode().equalsIgnoreCase("rightIndex"))
                                        nflops = 1.0 * (lsparse ? r1 * c1 * s1 
: r1 * c1); //FIXME
                                break;
                        }
@@ -545,7 +593,7 @@ public class LineageCache {
                }
                String outfile = outdir+"/"+_cache.get(_end._key)._key.getId();
                try {
-                       LocalFileUtils.writeMatrixBlockToLocal(outfile, 
_cache.get(_end._key).getValue());
+                       LocalFileUtils.writeMatrixBlockToLocal(outfile, 
_cache.get(_end._key).getMBValue());
                } catch (IOException e) {
                        throw new DMLRuntimeException ("Write to " + outfile + 
" failed.", e);
                }
@@ -558,7 +606,7 @@ public class LineageCache {
                _spillList.put(_end._key, new SpilledItem(outfile, 
_end._compEst));
        }
        
-       private static MatrixBlock readFromLocalFS(LineageItem key) {
+       private static Entry readFromLocalFS(LineageItem key) {
                long t0 = DMLScript.STATISTICS ? System.nanoTime() : 0;
                MatrixBlock mb = null;
                // Read from local FS
@@ -569,14 +617,14 @@ public class LineageCache {
                }
                // Restore to cache
                LocalFileUtils.deleteFileIfExists(_spillList.get(key)._outfile, 
true);
-               putIntern(key, mb, _spillList.get(key)._compEst);
+               putIntern(key, mb, null, _spillList.get(key)._compEst);
                _spillList.remove(key);
                if (DMLScript.STATISTICS) {
                        long t1 = System.nanoTime();
                        LineageCacheStatistics.incrementFSReadTime(t1-t0);
                        LineageCacheStatistics.incrementFSHits();
                }
-               return mb;
+               return _cache.get(key);
        }
 
        //------------------ LINKEDLIST MAINTENANCE METHODS -------------------
@@ -623,41 +671,72 @@ public class LineageCache {
                _cache.remove(key);
        }
        
-       private static class Entry {
+       static class Entry {
                private final LineageItem _key;
-               private MatrixBlock _val;
+               private MatrixBlock _MBval;
+               private ScalarObject _SOval;
                double _compEst;
                private Entry _prev;
                private Entry _next;
                private LineageItem _origItem;
                
-               public Entry(LineageItem key, MatrixBlock value, double 
computecost) {
+               public Entry(LineageItem key, MatrixBlock Mval, ScalarObject 
Sval, double computecost) {
                        _key = key;
-                       _val = value;
+                       _MBval = Mval;
+                       _SOval = Sval;
                        _compEst = computecost;
                        _origItem = null;
                }
 
-               public synchronized MatrixBlock getValue() {
+               public synchronized MatrixBlock getMBValue() {
                        try {
                                //wait until other thread completes operation
                                //in order to avoid redundant computation
-                               while( _val == null ) {
+                               while( _MBval == null ) {
                                        wait();
                                }
-                               return _val;
+                               return _MBval;
+                       }
+                       catch( InterruptedException ex ) {
+                               throw new DMLRuntimeException(ex);
+                       }
+               }
+
+               public synchronized ScalarObject getSOValue() {
+                       try {
+                               //wait until other thread completes operation
+                               //in order to avoid redundant computation
+                               while( _SOval == null ) {
+                                       wait();
+                               }
+                               return _SOval;
                        }
                        catch( InterruptedException ex ) {
                                throw new DMLRuntimeException(ex);
                        }
                }
                
+               public synchronized long getSize() {
+                       return ((_MBval != null ? _MBval.getInMemorySize() : 0) 
+ (_SOval != null ? _SOval.getSize() : 0));
+               }
+               
                public boolean isNullVal() {
-                       return(_val == null);
+                       return(_MBval == null && _SOval == null);
+               }
+               
+               public boolean isMatrixValue() {
+                       return(_MBval != null);
                }
                
                public synchronized void setValue(MatrixBlock val, double 
compEst) {
-                       _val = val;
+                       _MBval = val;
+                       _compEst = compEst;
+                       notifyAll();
+               }
+
+               public synchronized void setValue(MatrixBlock mval, 
ScalarObject so, double compEst) {
+                       _MBval = mval;
+                       _SOval = so;
                        _compEst = compEst;
                        notifyAll();
                }
diff --git 
a/src/main/java/org/apache/sysds/runtime/lineage/LineageCacheConfig.java 
b/src/main/java/org/apache/sysds/runtime/lineage/LineageCacheConfig.java
index 2615cdb..e4ce09b 100644
--- a/src/main/java/org/apache/sysds/runtime/lineage/LineageCacheConfig.java
+++ b/src/main/java/org/apache/sysds/runtime/lineage/LineageCacheConfig.java
@@ -27,14 +27,18 @@ public class LineageCacheConfig {
        public enum ReuseCacheType {
                REUSE_FULL,
                REUSE_PARTIAL,
+               REUSE_MULTILEVEL,
                REUSE_HYBRID,
                NONE;
                public boolean isFullReuse() {
-                       return this == REUSE_FULL || this == REUSE_HYBRID;
+                       return this == REUSE_FULL || this == REUSE_MULTILEVEL 
|| this == REUSE_HYBRID;
                }
                public boolean isPartialReuse() {
                        return this == REUSE_PARTIAL || this == REUSE_HYBRID;
                }
+               public boolean isMultilevelReuse() {
+                       return this == REUSE_MULTILEVEL || this == REUSE_HYBRID;
+               }
                public static boolean isNone() {
                        return DMLScript.LINEAGE_REUSE == null
                                || DMLScript.LINEAGE_REUSE == NONE;
@@ -102,7 +106,7 @@ public class LineageCacheConfig {
        public static boolean isSetSpill() {
                return _allowSpill;
        }
-       
+
        public static ReuseCacheType getCacheType() {
                return _cacheType;
        }
diff --git 
a/src/main/java/org/apache/sysds/runtime/lineage/LineageCacheStatistics.java 
b/src/main/java/org/apache/sysds/runtime/lineage/LineageCacheStatistics.java
index f3fdd20..98ad75e 100644
--- a/src/main/java/org/apache/sysds/runtime/lineage/LineageCacheStatistics.java
+++ b/src/main/java/org/apache/sysds/runtime/lineage/LineageCacheStatistics.java
@@ -94,7 +94,7 @@ public class LineageCacheStatistics {
        }
 
        public static void incrementPRewrites() {
-               // Number of times written in local FS.
+               // Number of partial rewrites.
                _numRewrites.increment();
        }
 
@@ -119,7 +119,7 @@ public class LineageCacheStatistics {
        }
 
        public static void incrementPRewriteTime(long delta) {
-               // Total time spent executing lineage rewrites.
+               // Total time spent compiling lineage rewrites.
                _ctimeRewrite.add(delta);
        }
 
diff --git 
a/src/main/java/org/apache/sysds/runtime/lineage/LineageCodegenItem.java 
b/src/main/java/org/apache/sysds/runtime/lineage/LineageCodegenItem.java
index 688a78c..5f24c89 100644
--- a/src/main/java/org/apache/sysds/runtime/lineage/LineageCodegenItem.java
+++ b/src/main/java/org/apache/sysds/runtime/lineage/LineageCodegenItem.java
@@ -25,6 +25,10 @@ import java.util.Map;
 public class LineageCodegenItem {
        private static Map<String, LineageItem> _codegentraces = new 
HashMap<>();
 
+       public static void reset() {
+               _codegentraces.clear();
+       }
+       
        public static LineageItem setCodegenLTrace(String classname, 
LineageItem li) {
                return _codegentraces.put(classname, li);
        }
diff --git a/src/main/java/org/apache/sysds/runtime/lineage/LineageMap.java 
b/src/main/java/org/apache/sysds/runtime/lineage/LineageMap.java
index 56fb725..0c4947e 100644
--- a/src/main/java/org/apache/sysds/runtime/lineage/LineageMap.java
+++ b/src/main/java/org/apache/sysds/runtime/lineage/LineageMap.java
@@ -36,14 +36,16 @@ import java.util.Map;
 
 public class LineageMap {
        
-       private Map<String, LineageItem> _traces = new HashMap<>();
-       private Map<String, LineageItem> _literals = new HashMap<>();
+       private final Map<String, LineageItem> _traces;
+       private final Map<String, LineageItem> _literals;
        
        public LineageMap() {
-       
+               _traces = new HashMap<>();
+               _literals = new HashMap<>();
        }
        
        public LineageMap(LineageMap that) {
+               this();
                _traces.putAll(that._traces);
                _literals.putAll(that._literals);
        }
diff --git a/src/main/java/org/apache/sysds/runtime/lineage/LineageParser.java 
b/src/main/java/org/apache/sysds/runtime/lineage/LineageParser.java
index e30dba7..d6b9ab8 100644
--- a/src/main/java/org/apache/sysds/runtime/lineage/LineageParser.java
+++ b/src/main/java/org/apache/sysds/runtime/lineage/LineageParser.java
@@ -31,9 +31,9 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 
-public class LineageParser {
-       
-       public static LineageTokenizer lineageTraceTokenizer = new 
LineageTokenizer();
+public class LineageParser
+{
+       public final static LineageTokenizer lineageTraceTokenizer = new 
LineageTokenizer();
        
        static {
                lineageTraceTokenizer.add("\\(");
diff --git 
a/src/main/java/org/apache/sysds/runtime/lineage/LineageRewriteReuse.java 
b/src/main/java/org/apache/sysds/runtime/lineage/LineageRewriteReuse.java
index 8a31f3b..fb5a21f 100644
--- a/src/main/java/org/apache/sysds/runtime/lineage/LineageRewriteReuse.java
+++ b/src/main/java/org/apache/sysds/runtime/lineage/LineageRewriteReuse.java
@@ -100,7 +100,11 @@ public class LineageRewriteReuse
 
                //put the result into the cache
                LineageCache.put(curr, ec);
-               DMLScript.EXPLAIN = et;
+               DMLScript.EXPLAIN = et; //TODO can't change this here
+               
+               //cleanup execution context
+               lrwec.getVariables().removeAll();
+               
                return true;
        }
        
@@ -195,11 +199,6 @@ public class LineageRewriteReuse
                BinaryOp lrwHop = HopRewriteUtils.createBinary(lastRes, 
tsmm_lr, OpOp2.PLUS);
                DataOp lrwWrite = HopRewriteUtils.createTransientWrite(LR_VAR, 
lrwHop);
 
-               if (DMLScript.STATISTICS) {
-                       
LineageCacheStatistics.incrementPRewriteTime(System.nanoTime() - t0);
-                       LineageCacheStatistics.incrementPRewrites();
-               }
-               
                // generate runtime instructions
                LOG.debug("LINEAGE REWRITE rewriteTsmmRbind APPLIED");
                ArrayList<Instruction> inst = genInst(lrwWrite, lrwec);
@@ -262,11 +261,6 @@ public class LineageRewriteReuse
                NaryOp lrwHop = HopRewriteUtils.createNary(OpOpN.RBIND, rowOne, 
newCol, rowTwo);
                DataOp lrwWrite = HopRewriteUtils.createTransientWrite(LR_VAR, 
lrwHop);
 
-               if (DMLScript.STATISTICS) {
-                       
LineageCacheStatistics.incrementPRewriteTime(System.nanoTime() - t0);
-                       LineageCacheStatistics.incrementPRewrites();
-               }
-
                // generate runtime instructions
                LOG.debug("LINEAGE REWRITE rewriteTsmm2Cbind APPLIED");
                ArrayList<Instruction> inst = genInst(lrwWrite, lrwec);
@@ -311,11 +305,6 @@ public class LineageRewriteReuse
                BinaryOp lrwHop= HopRewriteUtils.createBinary(lastRes, rowTwo, 
OpOp2.RBIND);
                DataOp lrwWrite = HopRewriteUtils.createTransientWrite(LR_VAR, 
lrwHop);
 
-               if (DMLScript.STATISTICS) {
-                       
LineageCacheStatistics.incrementPRewriteTime(System.nanoTime() - t0);
-                       LineageCacheStatistics.incrementPRewrites();
-               }
-               
                // generate runtime instructions
                LOG.debug("LINEAGE REWRITE rewriteMetMulRbindLeft APPLIED");
                ArrayList<Instruction> inst = genInst(lrwWrite, lrwec);
@@ -360,11 +349,6 @@ public class LineageRewriteReuse
                BinaryOp lrwHop= HopRewriteUtils.createBinary(lastRes, rowTwo, 
OpOp2.CBIND);
                DataOp lrwWrite = HopRewriteUtils.createTransientWrite(LR_VAR, 
lrwHop);
 
-               if (DMLScript.STATISTICS) {
-                       
LineageCacheStatistics.incrementPRewriteTime(System.nanoTime() - t0);
-                       LineageCacheStatistics.incrementPRewrites();
-               }
-               
                // generate runtime instructions
                LOG.debug("LINEAGE REWRITE rewriteMatMulCbindRight APPLIED");
                ArrayList<Instruction> inst = genInst(lrwWrite, lrwec);
@@ -420,11 +404,6 @@ public class LineageRewriteReuse
                BinaryOp lrwHop= HopRewriteUtils.createBinary(lastRes, rowTwo, 
OpOp2.RBIND);
                DataOp lrwWrite = HopRewriteUtils.createTransientWrite(LR_VAR, 
lrwHop);
 
-               if (DMLScript.STATISTICS) {
-                       
LineageCacheStatistics.incrementPRewriteTime(System.nanoTime() - t0);
-                       LineageCacheStatistics.incrementPRewrites();
-               }
-               
                // generate runtime instructions
                LOG.debug("LINEAGE REWRITE rewriteElementMulRbind APPLIED");
                ArrayList<Instruction> inst = genInst(lrwWrite, lrwec);
@@ -480,11 +459,6 @@ public class LineageRewriteReuse
                BinaryOp lrwHop= HopRewriteUtils.createBinary(lastRes, rowTwo, 
OpOp2.CBIND);
                DataOp lrwWrite = HopRewriteUtils.createTransientWrite(LR_VAR, 
lrwHop);
 
-               if (DMLScript.STATISTICS) {
-                       
LineageCacheStatistics.incrementPRewriteTime(System.nanoTime() - t0);
-                       LineageCacheStatistics.incrementPRewrites();
-               }
-               
                // generate runtime instructions
                LOG.debug("LINEAGE REWRITE rewriteElementMulCbind APPLIED");
                ArrayList<Instruction> inst = genInst(lrwWrite, lrwec);
@@ -540,11 +514,6 @@ public class LineageRewriteReuse
                BinaryOp lrwHop= HopRewriteUtils.createBinary(lastRes, rowTwo, 
OpOp2.CBIND);
                DataOp lrwWrite = HopRewriteUtils.createTransientWrite(LR_VAR, 
lrwHop);
 
-               if (DMLScript.STATISTICS) {
-                       
LineageCacheStatistics.incrementPRewriteTime(System.nanoTime() - t0);
-                       LineageCacheStatistics.incrementPRewrites();
-               }
-
                // generate runtime instructions
                LOG.debug("LINEAGE REWRITE rewriteElementMulCbind APPLIED");
                ArrayList<Instruction> inst = genInst(lrwWrite, lrwec);
@@ -574,10 +543,10 @@ public class LineageRewriteReuse
                                LineageItem input1 = source.getInputs()[0];
                                LineageItem tmp = new LineageItem("toProbe", 
curr.getOpcode(), new LineageItem[] {input1});
                                if (LineageCache.probe(tmp)) 
-                                       inCache.put("lastMatrix", 
LineageCache.get(tmp));
+                                       inCache.put("lastMatrix", 
LineageCache.get(tmp).getMBValue());
                                // look for the appended column in cache
                                if (LineageCache.probe(source.getInputs()[1])) 
-                                       inCache.put("deltaX", 
LineageCache.get(source.getInputs()[1]));
+                                       inCache.put("deltaX", 
LineageCache.get(source.getInputs()[1]).getMBValue());
                        }
                // return true only if the last tsmm is found
                return inCache.containsKey("lastMatrix") ? true : false;
@@ -597,10 +566,10 @@ public class LineageRewriteReuse
                                LineageItem input1 = source.getInputs()[0];
                                LineageItem tmp = new LineageItem("toProbe", 
curr.getOpcode(), new LineageItem[] {input1});
                                if (LineageCache.probe(tmp)) 
-                                       inCache.put("lastMatrix", 
LineageCache.get(tmp));
+                                       inCache.put("lastMatrix", 
LineageCache.get(tmp).getMBValue());
                                // look for the appended column in cache
                                if (LineageCache.probe(source.getInputs()[1])) 
-                                       inCache.put("deltaX", 
LineageCache.get(source.getInputs()[1]));
+                                       inCache.put("deltaX", 
LineageCache.get(source.getInputs()[1]).getMBValue());
                        }
                // return true only if the last tsmm is found
                return inCache.containsKey("lastMatrix") ? true : false;
@@ -624,10 +593,10 @@ public class LineageRewriteReuse
                                        LineageItem tmp = new 
LineageItem("comb", "cbind", new LineageItem[] {L2appin1, 
source.getInputs()[1]});
                                        LineageItem toProbe = new 
LineageItem("toProbe", curr.getOpcode(), new LineageItem[] {tmp});
                                        if (LineageCache.probe(toProbe)) 
-                                               inCache.put("lastMatrix", 
LineageCache.get(toProbe));
+                                               inCache.put("lastMatrix", 
LineageCache.get(toProbe).getMBValue());
                                        // look for the appended column in cache
                                        if 
(LineageCache.probe(input.getInputs()[1])) 
-                                               inCache.put("deltaX", 
LineageCache.get(input.getInputs()[1]));
+                                               inCache.put("deltaX", 
LineageCache.get(input.getInputs()[1]).getMBValue());
                                }
                        }
                // return true only if the last tsmm is found
@@ -649,10 +618,10 @@ public class LineageRewriteReuse
                                // create ba+* lineage on top of the input of 
last append
                                LineageItem tmp = new LineageItem("toProbe", 
curr.getOpcode(), new LineageItem[] {leftSource, right});
                                if (LineageCache.probe(tmp))
-                                       inCache.put("lastMatrix", 
LineageCache.get(tmp));
+                                       inCache.put("lastMatrix", 
LineageCache.get(tmp).getMBValue());
                                // look for the appended column in cache
                                if (LineageCache.probe(left.getInputs()[1])) 
-                                       inCache.put("deltaX", 
LineageCache.get(left.getInputs()[1]));
+                                       inCache.put("deltaX", 
LineageCache.get(left.getInputs()[1]).getMBValue());
                        }
                }
                // return true only if the last tsmm is found
@@ -674,10 +643,10 @@ public class LineageRewriteReuse
                                // create ba+* lineage on top of the input of 
last append
                                LineageItem tmp = new LineageItem("toProbe", 
curr.getOpcode(), new LineageItem[] {left, rightSource});
                                if (LineageCache.probe(tmp))
-                                       inCache.put("lastMatrix", 
LineageCache.get(tmp));
+                                       inCache.put("lastMatrix", 
LineageCache.get(tmp).getMBValue());
                                // look for the appended column in cache
                                if (LineageCache.probe(right.getInputs()[1])) 
-                                       inCache.put("deltaY", 
LineageCache.get(right.getInputs()[1]));
+                                       inCache.put("deltaY", 
LineageCache.get(right.getInputs()[1]).getMBValue());
                        }
                }
                return inCache.containsKey("lastMatrix") ? true : false;
@@ -699,12 +668,12 @@ public class LineageRewriteReuse
                                // create * lineage on top of the input of last 
append
                                LineageItem tmp = new LineageItem("toProbe", 
curr.getOpcode(), new LineageItem[] {leftSource, rightSource});
                                if (LineageCache.probe(tmp))
-                                       inCache.put("lastMatrix", 
LineageCache.get(tmp));
+                                       inCache.put("lastMatrix", 
LineageCache.get(tmp).getMBValue());
                                // look for the appended rows in cache
                                if (LineageCache.probe(left.getInputs()[1]))
-                                       inCache.put("deltaX", 
LineageCache.get(left.getInputs()[1]));
+                                       inCache.put("deltaX", 
LineageCache.get(left.getInputs()[1]).getMBValue());
                                if (LineageCache.probe(right.getInputs()[1]))
-                                       inCache.put("deltaY", 
LineageCache.get(right.getInputs()[1]));
+                                       inCache.put("deltaY", 
LineageCache.get(right.getInputs()[1]).getMBValue());
                        }
                }
                return inCache.containsKey("lastMatrix") ? true : false;
@@ -726,12 +695,12 @@ public class LineageRewriteReuse
                                // create * lineage on top of the input of last 
append
                                LineageItem tmp = new LineageItem("toProbe", 
curr.getOpcode(), new LineageItem[] {leftSource, rightSource});
                                if (LineageCache.probe(tmp))
-                                       inCache.put("lastMatrix", 
LineageCache.get(tmp));
+                                       inCache.put("lastMatrix", 
LineageCache.get(tmp).getMBValue());
                                // look for the appended columns in cache
                                if (LineageCache.probe(left.getInputs()[1]))
-                                       inCache.put("deltaX", 
LineageCache.get(left.getInputs()[1]));
+                                       inCache.put("deltaX", 
LineageCache.get(left.getInputs()[1]).getMBValue());
                                if (LineageCache.probe(right.getInputs()[1]))
-                                       inCache.put("deltaY", 
LineageCache.get(right.getInputs()[1]));
+                                       inCache.put("deltaY", 
LineageCache.get(right.getInputs()[1]).getMBValue());
                        }
                }
                return inCache.containsKey("lastMatrix") ? true : false;
@@ -757,10 +726,10 @@ public class LineageRewriteReuse
                                LineageItem tmp = new LineageItem("toProbe", 
curr.getOpcode(), 
                                                new LineageItem[] {input1, 
groups, weights, fn, ngroups});
                                if (LineageCache.probe(tmp)) 
-                                       inCache.put("lastMatrix", 
LineageCache.get(tmp));
+                                       inCache.put("lastMatrix", 
LineageCache.get(tmp).getMBValue());
                                // look for the appended column in cache
                                if (LineageCache.probe(target.getInputs()[1])) 
-                                       inCache.put("deltaX", 
LineageCache.get(target.getInputs()[1]));
+                                       inCache.put("deltaX", 
LineageCache.get(target.getInputs()[1]).getMBValue());
                        }
                }
                // return true only if the last tsmm is found
diff --git 
a/src/main/java/org/apache/sysds/runtime/lineage/LineageTokenizer.java 
b/src/main/java/org/apache/sysds/runtime/lineage/LineageTokenizer.java
index b32acd5..1056df0 100644
--- a/src/main/java/org/apache/sysds/runtime/lineage/LineageTokenizer.java
+++ b/src/main/java/org/apache/sysds/runtime/lineage/LineageTokenizer.java
@@ -32,7 +32,7 @@ import java.util.regex.Pattern;
 
 public class LineageTokenizer {
        
-       private List<TokenInfo> _tokenInfos;
+       private final List<TokenInfo> _tokenInfos;
        
        public LineageTokenizer() {
                _tokenInfos = new ArrayList<>();
diff --git 
a/src/test/java/org/apache/sysds/test/functions/lineage/FullReuseTest.java 
b/src/test/java/org/apache/sysds/test/functions/lineage/FullReuseTest.java
index 934d0d8..3d052e1 100644
--- a/src/test/java/org/apache/sysds/test/functions/lineage/FullReuseTest.java
+++ b/src/test/java/org/apache/sysds/test/functions/lineage/FullReuseTest.java
@@ -39,6 +39,7 @@ public class FullReuseTest extends AutomatedTestBase {
        protected static final String TEST_NAME1 = "FullReuse1";
        protected static final String TEST_NAME2 = "FullReuse2";
        protected static final String TEST_NAME3 = "FullReuse3";
+       protected static final String TEST_NAME4 = "FullReuse4";
        protected String TEST_CLASS_DIR = TEST_DIR + 
FullReuseTest.class.getSimpleName() + "/";
        
        @Override
@@ -47,6 +48,7 @@ public class FullReuseTest extends AutomatedTestBase {
                addTestConfiguration(TEST_NAME1, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME1));
                addTestConfiguration(TEST_NAME2, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME2));
                addTestConfiguration(TEST_NAME3, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME3));
+               addTestConfiguration(TEST_NAME4, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME4));
        }
        
        @Test
@@ -63,6 +65,11 @@ public class FullReuseTest extends AutomatedTestBase {
        public void testLineageTrace3() {
                testLineageTrace(TEST_NAME3);
        }
+
+       @Test
+       public void testLineageTrace4() {    //caching scalar
+               testLineageTrace(TEST_NAME4);
+       }
        
        public void testLineageTrace(String testname) {
                boolean old_simplification = 
OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION;
diff --git 
a/src/test/java/org/apache/sysds/test/functions/lineage/FunctionFullReuseTest.java
 
b/src/test/java/org/apache/sysds/test/functions/lineage/FunctionFullReuseTest.java
index 272e3e2..9819fe0 100644
--- 
a/src/test/java/org/apache/sysds/test/functions/lineage/FunctionFullReuseTest.java
+++ 
b/src/test/java/org/apache/sysds/test/functions/lineage/FunctionFullReuseTest.java
@@ -111,7 +111,7 @@ public class FunctionFullReuseTest extends 
AutomatedTestBase {
                        proArgs.clear();
                        proArgs.add("-stats");
                        proArgs.add("-lineage");
-                       
proArgs.add(ReuseCacheType.REUSE_FULL.name().toLowerCase());
+                       
proArgs.add(ReuseCacheType.REUSE_MULTILEVEL.name().toLowerCase());
                        proArgs.add("-args");
                        proArgs.add(output("X"));
                        programArgs = proArgs.toArray(new 
String[proArgs.size()]);
diff --git 
a/src/test/java/org/apache/sysds/test/functions/lineage/SBFullReuseTest.java 
b/src/test/java/org/apache/sysds/test/functions/lineage/SBFullReuseTest.java
index b3a33de..cabc349 100644
--- a/src/test/java/org/apache/sysds/test/functions/lineage/SBFullReuseTest.java
+++ b/src/test/java/org/apache/sysds/test/functions/lineage/SBFullReuseTest.java
@@ -97,7 +97,7 @@ public class SBFullReuseTest extends AutomatedTestBase {
                        proArgs.add("-stats");
                        proArgs.add("-explain");
                        proArgs.add("-lineage");
-                       
proArgs.add(ReuseCacheType.REUSE_FULL.name().toLowerCase());
+                       
proArgs.add(ReuseCacheType.REUSE_MULTILEVEL.name().toLowerCase());
                        proArgs.add("-args");
                        proArgs.add(output("X"));
                        programArgs = proArgs.toArray(new 
String[proArgs.size()]);
diff --git a/src/test/scripts/functions/lineage/FullReuse4.dml 
b/src/test/scripts/functions/lineage/FullReuse4.dml
new file mode 100644
index 0000000..fc3a2eb
--- /dev/null
+++ b/src/test/scripts/functions/lineage/FullReuse4.dml
@@ -0,0 +1,34 @@
+#-------------------------------------------------------------
+#
+# 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.
+#
+#-------------------------------------------------------------
+
+# Increase k for better performance gains
+
+X = rand(rows=1024, cols=1024, seed=42);
+k = 10
+
+for(i in 1:k){
+  t = sum(X) + nrow(X);  #cache scalar result
+  while(FALSE){}
+  tmp = X + t;
+}
+
+write(tmp, $1, format="text");
+

Reply via email to