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