This is an automated email from the ASF dual-hosted git repository.
arnabp20 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/systemds.git
The following commit(s) were added to refs/heads/master by this push:
new fd4b0d0 [SYSTEMDS-2889] Add initial lineage based debugger
fd4b0d0 is described below
commit fd4b0d05a38a29567c2a44d6c872c1f7d120cef8
Author: Benjamin Rath <[email protected]>
AuthorDate: Wed Jun 2 18:18:07 2021 +0200
[SYSTEMDS-2889] Add initial lineage based debugger
This patch adds a lineage based debugger which helps tracking
the first operator responsible for a constraint violation.
Currently, the supported constraints are NAN, positive infinity
and negative infinity.
AMLS project SS2021.
Closes #1286.
---
src/main/java/org/apache/sysds/api/DMLOptions.java | 3 +
src/main/java/org/apache/sysds/api/DMLScript.java | 2 +
.../controlprogram/context/ExecutionContext.java | 10 +-
.../runtime/instructions/cp/CPInstruction.java | 3 +
.../runtime/instructions/gpu/GPUInstruction.java | 3 +
.../sysds/runtime/lineage/BooleanArray32.java | 45 ++++
.../sysds/runtime/lineage/LineageDebugger.java | 108 ++++++++++
.../apache/sysds/runtime/lineage/LineageItem.java | 36 +++-
.../sysds/runtime/lineage/LineageItemUtils.java | 3 +
.../sysds/runtime/lineage/LineageParser.java | 6 +-
src/test/java/org/apache/sysds/test/TestUtils.java | 4 +
.../functions/lineage/LineageDebuggerTest.java | 236 +++++++++++++++++++++
.../scripts/functions/lineage/LineageDebugger1.dml | 39 ++++
13 files changed, 487 insertions(+), 11 deletions(-)
diff --git a/src/main/java/org/apache/sysds/api/DMLOptions.java
b/src/main/java/org/apache/sysds/api/DMLOptions.java
index a4dae4b..0949c06 100644
--- a/src/main/java/org/apache/sysds/api/DMLOptions.java
+++ b/src/main/java/org/apache/sysds/api/DMLOptions.java
@@ -66,6 +66,7 @@ public class DMLOptions {
public ReuseCacheType linReuseType = ReuseCacheType.NONE; //
reuse type (full, partial, hybrid)
public LineageCachePolicy linCachePolicy=
LineageCachePolicy.COSTNSIZE; // lineage cache eviction policy
public boolean lineage_estimate = false; //
whether estimate reuse benefits
+ public boolean lineage_debugger = false; //
whether enable lineage debugger
public boolean fedWorker = false;
public int fedWorkerPort = -1;
public boolean checkPrivacy = false; // Check
which privacy constraints are loaded and checked during federated execution
@@ -140,6 +141,8 @@ public class DMLOptions {
dmlOptions.linCachePolicy = LineageCachePolicy.DAGHEIGHT;
else if
(lineageType.equalsIgnoreCase("estimate"))
dmlOptions.lineage_estimate = lineageType.equalsIgnoreCase("estimate");
+ else if
(lineageType.equalsIgnoreCase("debugger"))
+
dmlOptions.lineage_debugger = lineageType.equalsIgnoreCase("debugger");
else
throw new
org.apache.commons.cli.ParseException(
"Invalid
argument specified for -lineage option: " + lineageType);
diff --git a/src/main/java/org/apache/sysds/api/DMLScript.java
b/src/main/java/org/apache/sysds/api/DMLScript.java
index c60fa3e..5072830 100644
--- a/src/main/java/org/apache/sysds/api/DMLScript.java
+++ b/src/main/java/org/apache/sysds/api/DMLScript.java
@@ -100,6 +100,7 @@ public class DMLScript
public static ReuseCacheType LINEAGE_REUSE =
DMLOptions.defaultOptions.linReuseType; // whether lineage-based reuse
public static LineageCachePolicy LINEAGE_POLICY =
DMLOptions.defaultOptions.linCachePolicy; // lineage cache eviction policy
public static boolean LINEAGE_ESTIMATE =
DMLOptions.defaultOptions.lineage_estimate; // whether estimate reuse benefits
+ public static boolean LINEAGE_DEBUGGER =
DMLOptions.defaultOptions.lineage_debugger; // whether enable lineage debugger
public static boolean CHECK_PRIVACY =
DMLOptions.defaultOptions.checkPrivacy; // Check which privacy constraints
are loaded and checked during federated execution
public static boolean USE_ACCELERATOR =
DMLOptions.defaultOptions.gpu;
@@ -224,6 +225,7 @@ public class DMLScript
LINEAGE_POLICY = dmlOptions.linCachePolicy;
LINEAGE_ESTIMATE = dmlOptions.lineage_estimate;
CHECK_PRIVACY = dmlOptions.checkPrivacy;
+ LINEAGE_DEBUGGER = dmlOptions.lineage_debugger;
String fnameOptConfig = dmlOptions.configFile;
boolean isFile = dmlOptions.filePath != null;
diff --git
a/src/main/java/org/apache/sysds/runtime/controlprogram/context/ExecutionContext.java
b/src/main/java/org/apache/sysds/runtime/controlprogram/context/ExecutionContext.java
index f0448f1..6b1054b 100644
---
a/src/main/java/org/apache/sysds/runtime/controlprogram/context/ExecutionContext.java
+++
b/src/main/java/org/apache/sysds/runtime/controlprogram/context/ExecutionContext.java
@@ -48,6 +48,7 @@ import
org.apache.sysds.runtime.instructions.gpu.context.CSRPointer;
import org.apache.sysds.runtime.instructions.gpu.context.GPUContext;
import org.apache.sysds.runtime.instructions.gpu.context.GPUObject;
import org.apache.sysds.runtime.lineage.Lineage;
+import org.apache.sysds.runtime.lineage.LineageDebugger;
import org.apache.sysds.runtime.lineage.LineageItem;
import org.apache.sysds.runtime.matrix.data.FrameBlock;
import org.apache.sysds.runtime.matrix.data.MatrixBlock;
@@ -808,9 +809,16 @@ public class ExecutionContext {
public void traceLineage(Instruction inst) {
if( _lineage == null )
throw new DMLRuntimeException("Lineage Trace
unavailable.");
+ // TODO bra: store all newly created lis in active list
_lineage.trace(inst, this);
}
-
+
+ public void maintainLineageDebuggerInfo(Instruction inst) {
+ if( _lineage == null )
+ throw new DMLRuntimeException("Lineage Trace
unavailable.");
+ LineageDebugger.maintainSpecialValueBits(_lineage, inst, this);
+ }
+
public LineageItem getLineageItem(CPOperand input) {
if( _lineage == null )
throw new DMLRuntimeException("Lineage Trace
unavailable.");
diff --git
a/src/main/java/org/apache/sysds/runtime/instructions/cp/CPInstruction.java
b/src/main/java/org/apache/sysds/runtime/instructions/cp/CPInstruction.java
index 014b854..84b2332 100644
--- a/src/main/java/org/apache/sysds/runtime/instructions/cp/CPInstruction.java
+++ b/src/main/java/org/apache/sysds/runtime/instructions/cp/CPInstruction.java
@@ -152,6 +152,9 @@ public abstract class CPInstruction extends Instruction
if (!LineageCacheConfig.ReuseCacheType.isNone() &&
DMLScript.USE_ACCELERATOR
&& LineageCacheConfig.CONCURRENTGPUEVICTION)
LineageCacheConfig.STOPBACKGROUNDEVICTION = true;
+
+ if (DMLScript.LINEAGE_DEBUGGER)
+ ec.maintainLineageDebuggerInfo(this);
}
/**
diff --git
a/src/main/java/org/apache/sysds/runtime/instructions/gpu/GPUInstruction.java
b/src/main/java/org/apache/sysds/runtime/instructions/gpu/GPUInstruction.java
index 4c51c70..700145b 100644
---
a/src/main/java/org/apache/sysds/runtime/instructions/gpu/GPUInstruction.java
+++
b/src/main/java/org/apache/sysds/runtime/instructions/gpu/GPUInstruction.java
@@ -226,6 +226,9 @@ public abstract class GPUInstruction extends Instruction
implements LineageTrace
if(gpuCtx != null)
gpuCtx.printMemoryInfo(getOpcode());
}
+
+ //default post-process behavior
+ super.postprocessInstruction(ec);
}
/**
diff --git a/src/main/java/org/apache/sysds/runtime/lineage/BooleanArray32.java
b/src/main/java/org/apache/sysds/runtime/lineage/BooleanArray32.java
new file mode 100644
index 0000000..f3cc5e6
--- /dev/null
+++ b/src/main/java/org/apache/sysds/runtime/lineage/BooleanArray32.java
@@ -0,0 +1,45 @@
+/*
+ * 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.sysds.runtime.lineage;
+
+public class BooleanArray32 {
+ private int _value;
+
+ public BooleanArray32(int value){
+ _value = value;
+ }
+
+ public boolean get(int pos) {
+ return (_value & (1 << pos)) != 0;
+ }
+
+ public void set(int pos, boolean value) {
+ int mask = 1 << pos;
+ _value = (_value & ~mask) | (value ? mask : 0);
+ }
+
+ public int getValue() {
+ return _value;
+ }
+
+ public void setValue(int value) {
+ _value = value;
+ }
+}
diff --git
a/src/main/java/org/apache/sysds/runtime/lineage/LineageDebugger.java
b/src/main/java/org/apache/sysds/runtime/lineage/LineageDebugger.java
new file mode 100644
index 0000000..1730c5a
--- /dev/null
+++ b/src/main/java/org/apache/sysds/runtime/lineage/LineageDebugger.java
@@ -0,0 +1,108 @@
+/*
+ * 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.sysds.runtime.lineage;
+
+
+import org.apache.sysds.runtime.controlprogram.caching.CacheableData;
+import org.apache.sysds.runtime.controlprogram.context.ExecutionContext;
+import org.apache.sysds.runtime.instructions.Instruction;
+import org.apache.sysds.runtime.instructions.cp.*;
+import org.apache.sysds.runtime.matrix.data.MatrixBlock;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Queue;
+import java.util.LinkedList;
+
+public class LineageDebugger {
+ public static final int POS_NAN = 0;
+ public static final int POS_POSITIVE_INFINITY = 1;
+ public static final int POS_NEGATIVE_INFINITY = 2;
+
+ public static void maintainSpecialValueBits(Lineage lineage,
Instruction inst, ExecutionContext ec) {
+ ArrayList<CPOperand> outputs = new ArrayList<>();
+
+ // Only CP instructions are supported right now
+ CPOperand singleOutput =
+ inst instanceof ComputationCPInstruction ?
((ComputationCPInstruction) inst).getOutput() :
+ inst instanceof BuiltinNaryCPInstruction ?
((BuiltinNaryCPInstruction) inst).getOutput() :
+ inst instanceof SqlCPInstruction ?
((SqlCPInstruction) inst).getOutput() :
+ inst instanceof VariableCPInstruction ?
((VariableCPInstruction) inst).getOutput() :
+ null;
+ if (singleOutput != null)
+ outputs.add(singleOutput);
+
+ Collection<CPOperand> multiOutputs =
+ inst instanceof MultiReturnBuiltinCPInstruction
? ((MultiReturnBuiltinCPInstruction) inst).getOutputs() :
+ inst instanceof
MultiReturnParameterizedBuiltinCPInstruction ?
((MultiReturnParameterizedBuiltinCPInstruction) inst).getOutputs() :
+ null;
+ if (multiOutputs != null)
+ outputs.addAll(multiOutputs);
+
+ for (CPOperand output : outputs) {
+ CacheableData<MatrixBlock> cd =
ec.getMatrixObject(output);
+ MatrixBlock mb = cd.acquireReadAndRelease();
+ LineageItem li = lineage.get(output);
+
+ updateSpecialValueBit(mb, li, POS_NAN, Double.NaN);
+ updateSpecialValueBit(mb, li, POS_POSITIVE_INFINITY,
Double.POSITIVE_INFINITY);
+ updateSpecialValueBit(mb, li, POS_NEGATIVE_INFINITY,
Double.NEGATIVE_INFINITY);
+ }
+ }
+
+ public static LineageItem firstOccurrenceOfNR(LineageItem li, int pos) {
+ if (!li.getSpecialValueBit(pos))
+ return null;
+
+ LineageItem tmp;
+ Queue<LineageItem> q = new LinkedList<>();
+ q.add(li);
+
+ while ((tmp = q.poll()) != null) {
+ if (tmp.isVisited())
+ continue;
+
+ if (tmp.getInputs() != null) {
+ boolean flag = false;
+ for (LineageItem in : tmp.getInputs()) {
+ flag |= in.getSpecialValueBit(pos);
+ q.add(in);
+ }
+ if (!flag)
+ break;
+ }
+ tmp.setVisited(true);
+ }
+ li.resetVisitStatusNR();
+ return tmp;
+ }
+
+ private static void updateSpecialValueBit(MatrixBlock mb, LineageItem
li, int pos, double pattern) {
+ boolean flag = false;
+ for (LineageItem input : li.getInputs()) {
+ if (input.getSpecialValueBit(pos)) {
+ flag = true;
+ break;
+ }
+ }
+ flag |= mb.containsValue(pattern);
+ li.setSpecialValueBit(pos, flag);
+ }
+}
diff --git a/src/main/java/org/apache/sysds/runtime/lineage/LineageItem.java
b/src/main/java/org/apache/sysds/runtime/lineage/LineageItem.java
index cd2346d..14b9894 100644
--- a/src/main/java/org/apache/sysds/runtime/lineage/LineageItem.java
+++ b/src/main/java/org/apache/sysds/runtime/lineage/LineageItem.java
@@ -37,6 +37,7 @@ public class LineageItem {
private int _hash = 0;
private LineageItem _dedupPatch;
private long _distLeaf2Node;
+ private final BooleanArray32 _specialValueBits; // TODO: Move this to
a new subclass
// init visited to true to ensure visited items are
// not hidden when used as inputs to new items
private boolean _visited = true;
@@ -53,30 +54,30 @@ public class LineageItem {
}
public LineageItem(long id, String data) {
- this(id, data, "", null);
+ this(id, data, "", null, 0);
}
public LineageItem(String data, String opcode) {
- this(_idSeq.getNextID(), data, opcode, null);
+ this(_idSeq.getNextID(), data, opcode, null, 0);
}
public LineageItem(String opcode, LineageItem[] inputs) {
- this(_idSeq.getNextID(), "", opcode, inputs);
+ this(_idSeq.getNextID(), "", opcode, inputs, 0);
}
public LineageItem(String data, String opcode, LineageItem[] inputs) {
- this(_idSeq.getNextID(), data, opcode, inputs);
+ this(_idSeq.getNextID(), data, opcode, inputs, 0);
}
public LineageItem(String opcode, LineageItem dedupPatch, LineageItem[]
inputs) {
- this(_idSeq.getNextID(), "", opcode, inputs);
+ this(_idSeq.getNextID(), "", opcode, inputs, 0);
// maintain a pointer to the dedup patch
_dedupPatch = dedupPatch;
_hash = _dedupPatch._hash;
}
public LineageItem(String opcode, LineageItem dedupPatch, int
dpatchHash, LineageItem[] inputs) {
- this(_idSeq.getNextID(), "", opcode, inputs);
+ this(_idSeq.getNextID(), "", opcode, inputs, 0);
// maintain a pointer to the dedup patch
_dedupPatch = dedupPatch;
_hash = dpatchHash;
@@ -87,14 +88,14 @@ public class LineageItem {
}
public LineageItem(long id, LineageItem li) {
- this(id, li._data, li._opcode, li._inputs);
+ this(id, li._data, li._opcode, li._inputs, 0);
}
public LineageItem(long id, String data, String opcode) {
- this(id, data, opcode, null);
+ this(id, data, opcode, null, 0);
}
- public LineageItem(long id, String data, String opcode, LineageItem[]
inputs) {
+ public LineageItem(long id, String data, String opcode, LineageItem[]
inputs, int specialValueBits) {
_id = id;
_opcode = opcode;
_data = data;
@@ -104,6 +105,7 @@ public class LineageItem {
_hash = hashCode();
// store the distance of this node from the leaves.
(O(#inputs)) operation
_distLeaf2Node = distLeaf2Node();
+ _specialValueBits = new BooleanArray32(specialValueBits);
}
public LineageItem[] getInputs() {
@@ -142,6 +144,14 @@ public class LineageItem {
_visited = flag;
}
+ public void setSpecialValueBit(int pos, boolean flag) {
+ _specialValueBits.set(pos, flag);
+ }
+
+ public void setSpecialValueBits(int value) {
+ _specialValueBits.setValue(value);
+ }
+
private long distLeaf2Node() {
// Derive height only if the corresponding reuse
// policy is selected, otherwise set -1.
@@ -169,6 +179,14 @@ public class LineageItem {
return _opcode;
}
+ public boolean getSpecialValueBit(int pos) {
+ return _specialValueBits.get(pos);
+ }
+
+ public int getSpecialValueBits() {
+ return _specialValueBits.getValue();
+ }
+
public boolean isPlaceholder() {
return _opcode.startsWith(LineageItemUtils.LPLACEHOLDER);
}
diff --git
a/src/main/java/org/apache/sysds/runtime/lineage/LineageItemUtils.java
b/src/main/java/org/apache/sysds/runtime/lineage/LineageItemUtils.java
index edd9a73..ca8d2cb 100644
--- a/src/main/java/org/apache/sysds/runtime/lineage/LineageItemUtils.java
+++ b/src/main/java/org/apache/sysds/runtime/lineage/LineageItemUtils.java
@@ -135,6 +135,9 @@ public class LineageItemUtils {
.map(i -> String.format("(%d)", i.getId()))
.collect(Collectors.joining(" "));
sb.append(ids);
+
+ if (DMLScript.LINEAGE_DEBUGGER)
+ sb.append("
").append("[").append(li.getSpecialValueBits()).append("]");
}
return sb.toString().trim();
}
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 46dff8e..439fe1f 100644
--- a/src/main/java/org/apache/sysds/runtime/lineage/LineageParser.java
+++ b/src/main/java/org/apache/sysds/runtime/lineage/LineageParser.java
@@ -108,15 +108,19 @@ public class LineageParser
}*/
ArrayList<LineageItem> inputs = new ArrayList<>();
+ int specialValueBits = 0;
for( int i=1; i<tokens.length; i++ ) {
String token = tokens[i];
if (token.startsWith("(") && token.endsWith(")")) {
token = token.substring(1, token.length()-1);
//rm parentheses
inputs.add(map.get(Long.valueOf(token)));
+ } else if (token.startsWith("[") &&
token.endsWith("]")) {
+ token = token.substring(1, token.length() - 1);
//rm parentheses
+ specialValueBits = Integer.parseInt(token);
} else
throw new ParseException("Invalid format for
LineageItem reference");
}
- return new LineageItem(id, "", opcode, inputs.toArray(new
LineageItem[0]));
+ return new LineageItem(id, "", opcode, inputs.toArray(new
LineageItem[0]), specialValueBits);
}
protected static void parseLineageTraceDedup(String str) {
diff --git a/src/test/java/org/apache/sysds/test/TestUtils.java
b/src/test/java/org/apache/sysds/test/TestUtils.java
index 42cec58..e8fdb2f 100644
--- a/src/test/java/org/apache/sysds/test/TestUtils.java
+++ b/src/test/java/org/apache/sysds/test/TestUtils.java
@@ -1020,6 +1020,10 @@ public class TestUtils
public static void compareScalars(String expected, String actual) {
assertEquals(expected, actual);
}
+
+ public static void compareScalars(Boolean expected, Boolean actual) {
+ assertEquals(expected, actual);
+ }
public static boolean compareMatrices(HashMap<CellIndex, Double> m1,
HashMap<CellIndex, Double> m2,
double tolerance, String name1, String name2)
diff --git
a/src/test/java/org/apache/sysds/test/functions/lineage/LineageDebuggerTest.java
b/src/test/java/org/apache/sysds/test/functions/lineage/LineageDebuggerTest.java
new file mode 100644
index 0000000..8f0cee5
--- /dev/null
+++
b/src/test/java/org/apache/sysds/test/functions/lineage/LineageDebuggerTest.java
@@ -0,0 +1,236 @@
+/*
+ * 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.sysds.test.functions.lineage;
+
+import org.apache.sysds.hops.OptimizerUtils;
+import org.apache.sysds.hops.recompile.Recompiler;
+import org.apache.sysds.runtime.lineage.Lineage;
+import org.apache.sysds.runtime.lineage.LineageDebugger;
+import org.apache.sysds.runtime.lineage.LineageItem;
+import org.apache.sysds.runtime.lineage.LineageParser;
+import org.apache.sysds.test.TestConfiguration;
+import org.apache.sysds.test.TestUtils;
+import org.apache.sysds.utils.Explain;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class LineageDebuggerTest extends LineageBase {
+
+ protected static final String TEST_DIR = "functions/lineage/";
+ protected static final String TEST_NAME1 = "LineageDebugger1";
+ protected String TEST_CLASS_DIR = TEST_DIR +
LineageDebuggerTest.class.getSimpleName() + "/";
+
+ protected static final int numRecords = 10;
+ protected static final int numFeatures = 5;
+
+
+ @Override
+ public void setUp() {
+ TestUtils.clearAssertionInformation();
+ addTestConfiguration(TEST_NAME1, new
TestConfiguration(TEST_CLASS_DIR, TEST_NAME1));
+ }
+
+ @Test
+ public void testLineageDebuggerNaN() {
+ testLineageDebuggerNaN(TEST_NAME1);
+ }
+
+ @Test
+ public void testLineageDebuggerInf1() {
+ testLineageDebuggerInf(TEST_NAME1, true, false);
+ }
+
+ @Test
+ public void testLineageDebuggerInf2() {
testLineageDebuggerInf(TEST_NAME1, false, true); }
+
+ @Test
+ public void testLineageDebuggerInf3() {
testLineageDebuggerInf(TEST_NAME1, true, true); }
+
+ @Test
+ public void testLineageDebuggerFirstOccurrence1() {
testLineageDebuggerFirstOccurrence(TEST_NAME1); }
+
+ public void testLineageDebuggerNaN(String testname) {
+ boolean old_simplification =
OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION;
+ boolean old_sum_product =
OptimizerUtils.ALLOW_SUM_PRODUCT_REWRITES;
+
+ try {
+ LOG.debug("------------ BEGIN " + testname +
"------------");
+
+ OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION = false;
+ OptimizerUtils.ALLOW_SUM_PRODUCT_REWRITES = false;
+
+ int rows = numRecords;
+ int cols = numFeatures;
+
+ getAndLoadTestConfiguration(testname);
+
+ List<String> proArgs = new ArrayList<>();
+
+ proArgs.add("-stats");
+ proArgs.add("-lineage");
+ proArgs.add("debugger");
+ proArgs.add("-args");
+ proArgs.add(input("X"));
+ proArgs.add(input("Y"));
+ proArgs.add(output("Z"));
+ programArgs = proArgs.toArray(new
String[proArgs.size()]);
+
+ fullDMLScriptName = getScript();
+
+ double[][] X = getRandomMatrix(rows, cols, 0, 1, 0.8,
-1);
+ writeInputMatrixWithMTD("X", X, true);
+
+ double[][] Y = getRandomMatrix(rows, cols, 0, 1, 0.8,
-1);
+ Y[3][3] = Double.NaN;
+ writeInputMatrixWithMTD("Y", Y, true);
+
+ Lineage.resetInternalState();
+ runTest(true, EXCEPTION_NOT_EXPECTED, null, -1);
+
+ String Z_lineage = readDMLLineageFromHDFS("Z");
+ LineageItem Z_li =
LineageParser.parseLineageTrace(Z_lineage);
+ TestUtils.compareScalars(Z_lineage,
Explain.explain(Z_li));
+
+ TestUtils.compareScalars(true,
Z_li.getSpecialValueBit(LineageDebugger.POS_NAN));
+ TestUtils.compareScalars(false,
Z_li.getSpecialValueBit(LineageDebugger.POS_NEGATIVE_INFINITY));
+ TestUtils.compareScalars(false,
Z_li.getSpecialValueBit(LineageDebugger.POS_POSITIVE_INFINITY));
+ }
+ finally {
+ OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION =
old_simplification;
+ OptimizerUtils.ALLOW_SUM_PRODUCT_REWRITES =
old_sum_product;
+ Recompiler.reinitRecompiler();
+ }
+ }
+
+ public void testLineageDebuggerInf(String testname, boolean positive,
boolean negative) {
+ boolean old_simplification =
OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION;
+ boolean old_sum_product =
OptimizerUtils.ALLOW_SUM_PRODUCT_REWRITES;
+
+ try {
+ LOG.debug("------------ BEGIN " + testname +
"------------");
+
+ OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION = false;
+ OptimizerUtils.ALLOW_SUM_PRODUCT_REWRITES = false;
+
+ int rows = numRecords;
+ int cols = numFeatures;
+
+ getAndLoadTestConfiguration(testname);
+
+ List<String> proArgs = new ArrayList<>();
+
+ proArgs.add("-stats");
+ proArgs.add("-lineage");
+ proArgs.add("debugger");
+ proArgs.add("-args");
+ proArgs.add(input("X"));
+ proArgs.add(input("Y"));
+ proArgs.add(output("Z"));
+ programArgs = proArgs.toArray(new
String[proArgs.size()]);
+
+ fullDMLScriptName = getScript();
+
+ double[][] X = getRandomMatrix(rows, cols, 0, 1, 0.8,
-1);
+ writeInputMatrixWithMTD("X", X, true);
+
+ double[][] Y = getRandomMatrix(rows, cols, 0, 1, 0.8,
-1);
+ if (positive)
+ Y[2][2] = Double.POSITIVE_INFINITY;
+ if (negative)
+ Y[3][3] = Double.NEGATIVE_INFINITY;
+ writeInputMatrixWithMTD("Y", Y, true);
+
+ Lineage.resetInternalState();
+ runTest(true, EXCEPTION_NOT_EXPECTED, null, -1);
+
+ String Z_lineage = readDMLLineageFromHDFS("Z");
+ LineageItem Z_li =
LineageParser.parseLineageTrace(Z_lineage);
+ TestUtils.compareScalars(Z_lineage,
Explain.explain(Z_li));
+
+ if (positive)
+ TestUtils.compareScalars(true,
Z_li.getSpecialValueBit(LineageDebugger.POS_POSITIVE_INFINITY));
+ if (negative)
+ TestUtils.compareScalars(true,
Z_li.getSpecialValueBit(LineageDebugger.POS_NEGATIVE_INFINITY));
+ }
+ finally {
+ OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION =
old_simplification;
+ OptimizerUtils.ALLOW_SUM_PRODUCT_REWRITES =
old_sum_product;
+ Recompiler.reinitRecompiler();
+ }
+ }
+
+ public void testLineageDebuggerFirstOccurrence(String testname) {
+ boolean old_simplification =
OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION;
+ boolean old_sum_product =
OptimizerUtils.ALLOW_SUM_PRODUCT_REWRITES;
+
+ try {
+ LOG.debug("------------ BEGIN " + testname +
"------------");
+
+ OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION = false;
+ OptimizerUtils.ALLOW_SUM_PRODUCT_REWRITES = false;
+
+ int rows = numRecords;
+ int cols = numFeatures;
+
+ getAndLoadTestConfiguration(testname);
+
+ List<String> proArgs = new ArrayList<>();
+
+ proArgs.add("-stats");
+ proArgs.add("-lineage");
+ proArgs.add("debugger");
+ proArgs.add("-args");
+ proArgs.add(input("X"));
+ proArgs.add(input("Y"));
+ proArgs.add(output("Z"));
+ programArgs = proArgs.toArray(new
String[proArgs.size()]);
+
+ fullDMLScriptName = getScript();
+
+ double[][] X = getRandomMatrix(rows, cols, 0, 1, 0.8,
-1);
+
+ writeInputMatrixWithMTD("X", X, true);
+
+ double[][] Y = getRandomMatrix(rows, cols, 0, 1, 0.8,
-1);
+ Y[3][3] = Double.NaN;
+ writeInputMatrixWithMTD("Y", Y, true);
+
+ Lineage.resetInternalState();
+ runTest(true, EXCEPTION_NOT_EXPECTED, null, -1);
+
+ String Z_lineage = readDMLLineageFromHDFS("Z");
+ LineageItem Z_li =
LineageParser.parseLineageTrace(Z_lineage);
+ TestUtils.compareScalars(Z_lineage,
Explain.explain(Z_li));
+
+ LineageItem firstOccurrence =
LineageDebugger.firstOccurrenceOfNR(Z_li, LineageDebugger.POS_NAN);
+ TestUtils.compareScalars(true,
firstOccurrence.getSpecialValueBit(LineageDebugger.POS_NAN));
+ for (LineageItem li : firstOccurrence.getInputs())
+ TestUtils.compareScalars(false,
li.getSpecialValueBit(LineageDebugger.POS_NAN));
+ }
+ finally {
+ OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION =
old_simplification;
+ OptimizerUtils.ALLOW_SUM_PRODUCT_REWRITES =
old_sum_product;
+ Recompiler.reinitRecompiler();
+ }
+ }
+
+}
diff --git a/src/test/scripts/functions/lineage/LineageDebugger1.dml
b/src/test/scripts/functions/lineage/LineageDebugger1.dml
new file mode 100644
index 0000000..6061b42
--- /dev/null
+++ b/src/test/scripts/functions/lineage/LineageDebugger1.dml
@@ -0,0 +1,39 @@
+#-------------------------------------------------------------
+#
+# 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.
+#
+#-------------------------------------------------------------
+
+# How to invoke this dml script LineageTrace.dml?
+# Assume LR_HOME is set to the home of the dml script
+# Assume rows = 20 and cols = 20 for X
+# hadoop jar SystemDS.jar -f $LR_HOME/LineageTrace.dml -args "$INPUT_DIR/X"
"$OUTPUT_DIR/X" "$OUTPUT_DIR/Y"
+
+X = read($1);
+Y = read($2);
+
+X = X + 3;
+X = X * 5;
+
+X = X * Y;
+
+Z = t(X) %*% X;
+
+# write(X, $3, format="text");
+# write(Y, $4, format="text");
+write(Z, $3, format="text");