| DEFAULT_WARMUP = 10 |
| DEFAULT_MEASURE = 3 |
| MODE = MODE || "compare" // MODE is often set on the command-line by run.sh |
| |
| /** |
| * label: for the printouts |
| * w: warmup runs |
| * m: measurement runs |
| * seq: closure to compute sequentially |
| * par: closure to compute in parallel |
| */ |
| function benchmark(label, w, m, seq, par) { |
| var SEQ = 1 |
| var PAR = 2 |
| var bits = 0 |
| if (MODE === "seq") { bits = SEQ; } |
| else if (MODE === "par") { bits = PAR; } |
| else { |
| if (MODE !== "compare") { |
| print("Invalid MODE, expected seq|par|compare: ", MODE); |
| } |
| bits = SEQ|PAR; |
| } |
| |
| if (mode(SEQ)) { |
| print("Warming up sequential runs"); |
| warmup(w, seq); |
| |
| print("Measuring sequential runs"); |
| var [seqTimes, seqResult] = measureN(m, seq); |
| } |
| |
| if (mode(PAR)) { |
| print("Warming up parallel runs"); |
| warmup(w, par); |
| |
| print("Measuring parallel runs"); |
| var [parTimes, parResult] = measureN(m, par); |
| } |
| |
| if (mode(SEQ|PAR)) { |
| // Check correctness |
| print("Checking correctness"); |
| assertStructuralEq(seqResult, parResult); |
| } |
| |
| if (mode(SEQ)) { |
| var seqAvg = average(seqTimes); |
| for (var i = 0; i < seqTimes.length; i++) |
| print(label + " SEQUENTIAL MEASUREMENT " + i + ": " + seqTimes[i]); |
| print(label + " SEQUENTIAL AVERAGE: " + seqAvg); |
| } |
| |
| if (mode(PAR)) { |
| var parAvg = average(parTimes); |
| for (var i = 0; i < parTimes.length; i++) |
| print(label + " PARALLEL MEASUREMENT " + i + ": " + parTimes[i]); |
| print(label + " PARALLEL AVERAGE : " + parAvg); |
| } |
| |
| if (mode(SEQ|PAR)) { |
| print(label + " SEQ/PAR RATIO : " + seqAvg/parAvg); |
| print(label + " PAR/SEQ RATIO : " + parAvg/seqAvg); |
| print(label + " IMPROVEMENT : " + |
| (((seqAvg - parAvg) / seqAvg * 100.0) | 0) + "%"); |
| } |
| |
| function mode(m) { |
| return (bits & m) === m; |
| } |
| } |
| |
| function measure1(f) { |
| var start = new Date(); |
| result = f(); |
| var end = new Date(); |
| return [end.getTime() - start.getTime(), result]; |
| } |
| |
| function warmup(iters, f) { |
| for (var i = 0; i < iters; i++) { |
| print("."); |
| f(); |
| } |
| } |
| |
| function average(measurements) { |
| var sum = measurements.reduce(function (x, y) { return x + y; }); |
| return sum / measurements.length; |
| } |
| |
| function measureN(iters, f) { |
| var measurement, measurements = []; |
| var result; |
| |
| for (var i = 0; i < iters; i++) { |
| [measurement, result] = measure1(f); |
| measurements.push(measurement); |
| } |
| |
| return [measurements, result]; |
| } |
| |
| function assertStructuralEq(e1, e2) { |
| if (e1 instanceof ParallelArray && e2 instanceof ParallelArray) { |
| assertEqParallelArray(e1, e2); |
| } else if (typeof(RectArray) != "undefined" && |
| e1 instanceof ParallelArray && e2 instanceof RectArray) { |
| assertEqParallelArrayRectArray(e1, e2); |
| } else if (typeof(RectArray) != "undefined" && |
| e1 instanceof RectArray && e2 instanceof ParallelArray) { |
| assertEqParallelArrayRectArray(e2, e1); |
| } else if (typeof(WrapArray) != "undefined" && |
| e1 instanceof ParallelArray && e2 instanceof WrapArray) { |
| assertEqParallelArrayWrapArray(e1, e2); |
| } else if (typeof(WrapArray) != "undefined" && |
| e1 instanceof WrapArray && e2 instanceof ParallelArray) { |
| assertEqParallelArrayWrapArray(e2, e1); |
| } else if (e1 instanceof Array && e2 instanceof ParallelArray) { |
| assertEqParallelArrayArray(e2, e1); |
| } else if (e1 instanceof ParallelArray && e2 instanceof Array) { |
| assertEqParallelArrayArray(e1, e2); |
| } else if (typeof(RectArray) != "undefined" && |
| e1 instanceof RectArray && e2 instanceof RectArray) { |
| assertEqRectArray(e1, e2); |
| } else if (typeof(WrapArray) != "undefined" && |
| e1 instanceof WrapArray && e2 instanceof WrapArray) { |
| assertEqWrapArray(e1, e2); |
| } else if (e1 instanceof Array && e2 instanceof Array) { |
| assertEqArray(e1, e2); |
| } else if (e1 instanceof Object && e2 instanceof Object) { |
| assertEq(e1.__proto__, e2.__proto__); |
| for (prop in e1) { |
| if (e1.hasOwnProperty(prop)) { |
| assertEq(e2.hasOwnProperty(prop), true); |
| assertStructuralEq(e1[prop], e2[prop]); |
| } |
| } |
| } else { |
| assertEq(e1, e2); |
| } |
| } |
| |
| function assertEqParallelArrayRectArray(a, b) { |
| assertEq(a.shape.length, 2); |
| assertEq(a.shape[0], b.width); |
| assertEq(a.shape[1], b.height); |
| for (var i = 0, w = a.shape[0]; i < w; i++) { |
| for (var j = 0, h = a.shape[1]; j < h; j++) { |
| assertStructuralEq(a.get(i,j), b.get(i,j)); |
| } |
| } |
| } |
| |
| function assertEqParallelArrayWrapArray(a, b) { |
| assertEq(a.shape.length, 2); |
| assertEq(a.shape[0], b.width); |
| assertEq(a.shape[1], b.height); |
| for (var i = 0, w = a.shape[0]; i < w; i++) { |
| for (var j = 0, h = a.shape[1]; j < h; j++) { |
| assertStructuralEq(a.get(i,j), b.get(i,j)); |
| } |
| } |
| } |
| |
| function assertEqParallelArrayArray(a, b) { |
| assertEq(a.shape.length, 1); |
| assertEq(a.length, b.length); |
| for (var i = 0, l = a.shape[0]; i < l; i++) { |
| assertStructuralEq(a.get(i), b[i]); |
| } |
| } |
| |
| function assertEqRectArray(a, b) { |
| assertEq(a.width, b.width); |
| assertEq(a.height, b.height); |
| for (var i = 0, w = a.width; i < w; i++) { |
| for (var j = 0, h = a.height; j < h; j++) { |
| assertStructuralEq(a.get(i,j), b.get(i,j)); |
| } |
| } |
| } |
| |
| function assertEqWrapArray(a, b) { |
| assertEq(a.width, b.width); |
| assertEq(a.height, b.height); |
| for (var i = 0, w = a.width; i < w; i++) { |
| for (var j = 0, h = a.height; j < h; j++) { |
| assertStructuralEq(a.get(i,j), b.get(i,j)); |
| } |
| } |
| } |
| |
| function assertEqArray(a, b) { |
| assertEq(a.length, b.length); |
| for (var i = 0, l = a.length; i < l; i++) { |
| assertStructuralEq(a[i], b[i]); |
| } |
| } |
| |
| function assertEqParallelArray(a, b) { |
| assertEq(a instanceof ParallelArray, true); |
| assertEq(b instanceof ParallelArray, true); |
| |
| var shape = a.shape; |
| assertEqArray(shape, b.shape); |
| |
| function bump(indices) { |
| var d = indices.length - 1; |
| while (d >= 0) { |
| if (++indices[d] < shape[d]) |
| break; |
| indices[d] = 0; |
| d--; |
| } |
| return d >= 0; |
| } |
| |
| var iv = shape.map(function () { return 0; }); |
| do { |
| var e1 = a.get.apply(a, iv); |
| var e2 = b.get.apply(b, iv); |
| assertStructuralEq(e1, e2); |
| } while (bump(iv)); |
| } |