|
19 | 19 |
|
20 | 20 | package org.apache.sysds.runtime.lineage; |
21 | 21 |
|
| 22 | +import org.apache.commons.lang3.tuple.MutablePair; |
| 23 | +import org.apache.commons.lang3.tuple.Pair; |
22 | 24 | import org.apache.sysds.api.DMLScript; |
23 | 25 | import org.apache.sysds.common.Types.DataType; |
24 | 26 | import org.apache.sysds.common.Types.FileFormat; |
|
45 | 47 | import org.apache.sysds.runtime.matrix.data.MatrixBlock; |
46 | 48 | import org.apache.sysds.runtime.meta.MetaDataFormat; |
47 | 49 |
|
| 50 | +import java.util.ArrayList; |
| 51 | +import java.util.Arrays; |
48 | 52 | import java.util.HashMap; |
49 | 53 | import java.util.List; |
50 | 54 | import java.util.Map; |
@@ -81,39 +85,40 @@ public static boolean reuse(Instruction inst, ExecutionContext ec) { |
81 | 85 | if (LineageCacheConfig.isReusable(inst, ec)) { |
82 | 86 | ComputationCPInstruction cinst = (ComputationCPInstruction) inst; |
83 | 87 | LineageItem instLI = cinst.getLineageItem(ec).getValue(); |
84 | | - HashMap<LineageItem, LineageCacheEntry> liMap = new HashMap<>(); |
| 88 | + List<MutablePair<LineageItem, LineageCacheEntry>> liList = null; |
85 | 89 | if (inst instanceof MultiReturnBuiltinCPInstruction) { |
| 90 | + liList = new ArrayList<>(); |
86 | 91 | MultiReturnBuiltinCPInstruction mrInst = (MultiReturnBuiltinCPInstruction)inst; |
87 | 92 | for (int i=0; i<mrInst.getNumOutputs(); i++) { |
88 | 93 | String opcode = instLI.getOpcode() + String.valueOf(i); |
89 | | - liMap.put(new LineageItem(opcode, instLI.getInputs()), null); |
| 94 | + liList.add(MutablePair.of(new LineageItem(opcode, instLI.getInputs()), null)); |
90 | 95 | } |
91 | 96 | } |
92 | 97 | else |
93 | | - liMap.put(instLI, null); |
| 98 | + liList = Arrays.asList(MutablePair.of(instLI, null)); |
94 | 99 |
|
95 | 100 | //atomic try reuse full/partial and set placeholder, without |
96 | 101 | //obtaining value to avoid blocking in critical section |
97 | 102 | LineageCacheEntry e = null; |
98 | 103 | boolean reuseAll = true; |
99 | 104 | synchronized( _cache ) { |
100 | 105 | //try to reuse full or partial intermediates |
101 | | - for (LineageItem item : liMap.keySet()) { |
| 106 | + for (MutablePair<LineageItem,LineageCacheEntry> item : liList) { |
102 | 107 | if (LineageCacheConfig.getCacheType().isFullReuse()) |
103 | | - e = LineageCache.probe(item) ? getIntern(item) : null; |
| 108 | + e = LineageCache.probe(item.getKey()) ? getIntern(item.getKey()) : null; |
104 | 109 | //TODO need to also move execution of compensation plan out of here |
105 | 110 | //(create lazily evaluated entry) |
106 | 111 | if (e == null && LineageCacheConfig.getCacheType().isPartialReuse()) |
107 | 112 | if( LineageRewriteReuse.executeRewrites(inst, ec) ) |
108 | | - e = getIntern(item); |
| 113 | + e = getIntern(item.getKey()); |
109 | 114 | //TODO: MultiReturnBuiltin and partial rewrites |
110 | 115 | reuseAll &= (e != null); |
111 | | - liMap.put(item, e); |
| 116 | + item.setValue(e); |
112 | 117 |
|
113 | 118 | //create a placeholder if no reuse to avoid redundancy |
114 | 119 | //(e.g., concurrent threads that try to start the computation) |
115 | 120 | if(e == null && isMarkedForCaching(inst, ec)) { |
116 | | - putIntern(item, cinst.output.getDataType(), null, null, 0); |
| 121 | + putIntern(item.getKey(), cinst.output.getDataType(), null, null, 0); |
117 | 122 | //FIXME: different o/p datatypes for MultiReturnBuiltins. |
118 | 123 | } |
119 | 124 | } |
@@ -122,7 +127,7 @@ public static boolean reuse(Instruction inst, ExecutionContext ec) { |
122 | 127 |
|
123 | 128 | if(reuse) { //reuse |
124 | 129 | //put reuse value into symbol table (w/ blocking on placeholders) |
125 | | - for (Map.Entry<LineageItem, LineageCacheEntry> entry : liMap.entrySet()) { |
| 130 | + for (MutablePair<LineageItem, LineageCacheEntry> entry : liList) { |
126 | 131 | e = entry.getValue(); |
127 | 132 | String outName = null; |
128 | 133 | if (inst instanceof MultiReturnBuiltinCPInstruction) |
@@ -243,39 +248,42 @@ public static void putMatrix(Instruction inst, ExecutionContext ec, long compute |
243 | 248 | } |
244 | 249 | } |
245 | 250 |
|
246 | | - public static void putValue(Instruction inst, ExecutionContext ec, long computetime) { |
| 251 | + public static void putValue(Instruction inst, ExecutionContext ec, long starttime) { |
247 | 252 | if (ReuseCacheType.isNone()) |
248 | 253 | return; |
| 254 | + long computetime = System.nanoTime() - starttime; |
249 | 255 | if (LineageCacheConfig.isReusable(inst, ec) ) { |
250 | 256 | //if (!isMarkedForCaching(inst, ec)) return; |
251 | | - HashMap<LineageItem, Data> liDataMap = new HashMap<>(); |
| 257 | + List<Pair<LineageItem, Data>> liData = null; |
252 | 258 | LineageItem instLI = ((LineageTraceable) inst).getLineageItem(ec).getValue(); |
253 | 259 | if (inst instanceof MultiReturnBuiltinCPInstruction) { |
| 260 | + liData = new ArrayList<>(); |
254 | 261 | MultiReturnBuiltinCPInstruction mrInst = (MultiReturnBuiltinCPInstruction)inst; |
255 | 262 | for (int i=0; i<mrInst.getNumOutputs(); i++) { |
256 | 263 | String opcode = instLI.getOpcode() + String.valueOf(i); |
257 | 264 | LineageItem li = new LineageItem(opcode, instLI.getInputs()); |
258 | 265 | Data value = ec.getVariable(mrInst.getOutput(i)); |
259 | | - liDataMap.put(li, value); |
| 266 | + liData.add(Pair.of(li, value)); |
260 | 267 | } |
261 | 268 | } |
262 | 269 | else |
263 | | - liDataMap.put(instLI, ec.getVariable(((ComputationCPInstruction) inst).output)); |
| 270 | + liData = Arrays.asList(Pair.of(instLI, ec.getVariable(((ComputationCPInstruction) inst).output))); |
264 | 271 | synchronized( _cache ) { |
265 | | - for (Map.Entry<LineageItem, Data> entry : liDataMap.entrySet()) { |
| 272 | + for (Pair<LineageItem, Data> entry : liData) { |
266 | 273 | LineageItem item = entry.getKey(); |
267 | 274 | Data data = entry.getValue(); |
| 275 | + LineageCacheEntry centry = _cache.get(item); |
268 | 276 | if (data instanceof MatrixObject) |
269 | | - _cache.get(item).setValue(((MatrixObject)data).acquireReadAndRelease(), computetime); |
| 277 | + centry.setValue(((MatrixObject)data).acquireReadAndRelease(), computetime); |
270 | 278 | else if (data instanceof ScalarObject) |
271 | | - _cache.get(item).setValue((ScalarObject)data, computetime); |
| 279 | + centry.setValue((ScalarObject)data, computetime); |
272 | 280 | else |
273 | 281 | throw new DMLRuntimeException("Lineage Cache: unsupported data: "+data.getDataType()); |
274 | 282 |
|
275 | 283 | //maintain order for eviction |
276 | | - LineageCacheEviction.addEntry(_cache.get(item)); |
| 284 | + LineageCacheEviction.addEntry(centry); |
277 | 285 |
|
278 | | - long size = _cache.get(item).getSize(); |
| 286 | + long size = centry.getSize(); |
279 | 287 | if (!LineageCacheEviction.isBelowThreshold(size)) |
280 | 288 | LineageCacheEviction.makeSpace(_cache, size); |
281 | 289 | LineageCacheEviction.updateSize(size, true); |
@@ -284,8 +292,8 @@ else if (data instanceof ScalarObject) |
284 | 292 | } |
285 | 293 | } |
286 | 294 |
|
287 | | - public static void putValue(List<DataIdentifier> outputs, LineageItem[] liInputs, |
288 | | - String name, ExecutionContext ec, long computetime) |
| 295 | + public static void putValue(List<DataIdentifier> outputs, |
| 296 | + LineageItem[] liInputs, String name, ExecutionContext ec, long computetime) |
289 | 297 | { |
290 | 298 | if (!LineageCacheConfig.isMultiLevelReuse()) |
291 | 299 | return; |
|