|
1 DEFAULT_WARMUP = 10 |
|
2 DEFAULT_MEASURE = 3 |
|
3 MODE = MODE || "compare" // MODE is often set on the command-line by run.sh |
|
4 |
|
5 /** |
|
6 * label: for the printouts |
|
7 * w: warmup runs |
|
8 * m: measurement runs |
|
9 * seq: closure to compute sequentially |
|
10 * par: closure to compute in parallel |
|
11 */ |
|
12 function benchmark(label, w, m, seq, par) { |
|
13 var SEQ = 1 |
|
14 var PAR = 2 |
|
15 var bits = 0 |
|
16 if (MODE === "seq") { bits = SEQ; } |
|
17 else if (MODE === "par") { bits = PAR; } |
|
18 else { |
|
19 if (MODE !== "compare") { |
|
20 print("Invalid MODE, expected seq|par|compare: ", MODE); |
|
21 } |
|
22 bits = SEQ|PAR; |
|
23 } |
|
24 |
|
25 if (mode(SEQ)) { |
|
26 print("Warming up sequential runs"); |
|
27 warmup(w, seq); |
|
28 |
|
29 print("Measuring sequential runs"); |
|
30 var [seqTimes, seqResult] = measureN(m, seq); |
|
31 } |
|
32 |
|
33 if (mode(PAR)) { |
|
34 print("Warming up parallel runs"); |
|
35 warmup(w, par); |
|
36 |
|
37 print("Measuring parallel runs"); |
|
38 var [parTimes, parResult] = measureN(m, par); |
|
39 } |
|
40 |
|
41 if (mode(SEQ|PAR)) { |
|
42 // Check correctness |
|
43 print("Checking correctness"); |
|
44 assertStructuralEq(seqResult, parResult); |
|
45 } |
|
46 |
|
47 if (mode(SEQ)) { |
|
48 var seqAvg = average(seqTimes); |
|
49 for (var i = 0; i < seqTimes.length; i++) |
|
50 print(label + " SEQUENTIAL MEASUREMENT " + i + ": " + seqTimes[i]); |
|
51 print(label + " SEQUENTIAL AVERAGE: " + seqAvg); |
|
52 } |
|
53 |
|
54 if (mode(PAR)) { |
|
55 var parAvg = average(parTimes); |
|
56 for (var i = 0; i < parTimes.length; i++) |
|
57 print(label + " PARALLEL MEASUREMENT " + i + ": " + parTimes[i]); |
|
58 print(label + " PARALLEL AVERAGE : " + parAvg); |
|
59 } |
|
60 |
|
61 if (mode(SEQ|PAR)) { |
|
62 print(label + " SEQ/PAR RATIO : " + seqAvg/parAvg); |
|
63 print(label + " PAR/SEQ RATIO : " + parAvg/seqAvg); |
|
64 print(label + " IMPROVEMENT : " + |
|
65 (((seqAvg - parAvg) / seqAvg * 100.0) | 0) + "%"); |
|
66 } |
|
67 |
|
68 function mode(m) { |
|
69 return (bits & m) === m; |
|
70 } |
|
71 } |
|
72 |
|
73 function measure1(f) { |
|
74 var start = new Date(); |
|
75 result = f(); |
|
76 var end = new Date(); |
|
77 return [end.getTime() - start.getTime(), result]; |
|
78 } |
|
79 |
|
80 function warmup(iters, f) { |
|
81 for (var i = 0; i < iters; i++) { |
|
82 print("."); |
|
83 f(); |
|
84 } |
|
85 } |
|
86 |
|
87 function average(measurements) { |
|
88 var sum = measurements.reduce(function (x, y) { return x + y; }); |
|
89 return sum / measurements.length; |
|
90 } |
|
91 |
|
92 function measureN(iters, f) { |
|
93 var measurement, measurements = []; |
|
94 var result; |
|
95 |
|
96 for (var i = 0; i < iters; i++) { |
|
97 [measurement, result] = measure1(f); |
|
98 measurements.push(measurement); |
|
99 } |
|
100 |
|
101 return [measurements, result]; |
|
102 } |
|
103 |
|
104 function assertStructuralEq(e1, e2) { |
|
105 if (e1 instanceof ParallelArray && e2 instanceof ParallelArray) { |
|
106 assertEqParallelArray(e1, e2); |
|
107 } else if (typeof(RectArray) != "undefined" && |
|
108 e1 instanceof ParallelArray && e2 instanceof RectArray) { |
|
109 assertEqParallelArrayRectArray(e1, e2); |
|
110 } else if (typeof(RectArray) != "undefined" && |
|
111 e1 instanceof RectArray && e2 instanceof ParallelArray) { |
|
112 assertEqParallelArrayRectArray(e2, e1); |
|
113 } else if (typeof(WrapArray) != "undefined" && |
|
114 e1 instanceof ParallelArray && e2 instanceof WrapArray) { |
|
115 assertEqParallelArrayWrapArray(e1, e2); |
|
116 } else if (typeof(WrapArray) != "undefined" && |
|
117 e1 instanceof WrapArray && e2 instanceof ParallelArray) { |
|
118 assertEqParallelArrayWrapArray(e2, e1); |
|
119 } else if (e1 instanceof Array && e2 instanceof ParallelArray) { |
|
120 assertEqParallelArrayArray(e2, e1); |
|
121 } else if (e1 instanceof ParallelArray && e2 instanceof Array) { |
|
122 assertEqParallelArrayArray(e1, e2); |
|
123 } else if (typeof(RectArray) != "undefined" && |
|
124 e1 instanceof RectArray && e2 instanceof RectArray) { |
|
125 assertEqRectArray(e1, e2); |
|
126 } else if (typeof(WrapArray) != "undefined" && |
|
127 e1 instanceof WrapArray && e2 instanceof WrapArray) { |
|
128 assertEqWrapArray(e1, e2); |
|
129 } else if (e1 instanceof Array && e2 instanceof Array) { |
|
130 assertEqArray(e1, e2); |
|
131 } else if (e1 instanceof Object && e2 instanceof Object) { |
|
132 assertEq(e1.__proto__, e2.__proto__); |
|
133 for (prop in e1) { |
|
134 if (e1.hasOwnProperty(prop)) { |
|
135 assertEq(e2.hasOwnProperty(prop), true); |
|
136 assertStructuralEq(e1[prop], e2[prop]); |
|
137 } |
|
138 } |
|
139 } else { |
|
140 assertEq(e1, e2); |
|
141 } |
|
142 } |
|
143 |
|
144 function assertEqParallelArrayRectArray(a, b) { |
|
145 assertEq(a.shape.length, 2); |
|
146 assertEq(a.shape[0], b.width); |
|
147 assertEq(a.shape[1], b.height); |
|
148 for (var i = 0, w = a.shape[0]; i < w; i++) { |
|
149 for (var j = 0, h = a.shape[1]; j < h; j++) { |
|
150 assertStructuralEq(a.get(i,j), b.get(i,j)); |
|
151 } |
|
152 } |
|
153 } |
|
154 |
|
155 function assertEqParallelArrayWrapArray(a, b) { |
|
156 assertEq(a.shape.length, 2); |
|
157 assertEq(a.shape[0], b.width); |
|
158 assertEq(a.shape[1], b.height); |
|
159 for (var i = 0, w = a.shape[0]; i < w; i++) { |
|
160 for (var j = 0, h = a.shape[1]; j < h; j++) { |
|
161 assertStructuralEq(a.get(i,j), b.get(i,j)); |
|
162 } |
|
163 } |
|
164 } |
|
165 |
|
166 function assertEqParallelArrayArray(a, b) { |
|
167 assertEq(a.shape.length, 1); |
|
168 assertEq(a.length, b.length); |
|
169 for (var i = 0, l = a.shape[0]; i < l; i++) { |
|
170 assertStructuralEq(a.get(i), b[i]); |
|
171 } |
|
172 } |
|
173 |
|
174 function assertEqRectArray(a, b) { |
|
175 assertEq(a.width, b.width); |
|
176 assertEq(a.height, b.height); |
|
177 for (var i = 0, w = a.width; i < w; i++) { |
|
178 for (var j = 0, h = a.height; j < h; j++) { |
|
179 assertStructuralEq(a.get(i,j), b.get(i,j)); |
|
180 } |
|
181 } |
|
182 } |
|
183 |
|
184 function assertEqWrapArray(a, b) { |
|
185 assertEq(a.width, b.width); |
|
186 assertEq(a.height, b.height); |
|
187 for (var i = 0, w = a.width; i < w; i++) { |
|
188 for (var j = 0, h = a.height; j < h; j++) { |
|
189 assertStructuralEq(a.get(i,j), b.get(i,j)); |
|
190 } |
|
191 } |
|
192 } |
|
193 |
|
194 function assertEqArray(a, b) { |
|
195 assertEq(a.length, b.length); |
|
196 for (var i = 0, l = a.length; i < l; i++) { |
|
197 assertStructuralEq(a[i], b[i]); |
|
198 } |
|
199 } |
|
200 |
|
201 function assertEqParallelArray(a, b) { |
|
202 assertEq(a instanceof ParallelArray, true); |
|
203 assertEq(b instanceof ParallelArray, true); |
|
204 |
|
205 var shape = a.shape; |
|
206 assertEqArray(shape, b.shape); |
|
207 |
|
208 function bump(indices) { |
|
209 var d = indices.length - 1; |
|
210 while (d >= 0) { |
|
211 if (++indices[d] < shape[d]) |
|
212 break; |
|
213 indices[d] = 0; |
|
214 d--; |
|
215 } |
|
216 return d >= 0; |
|
217 } |
|
218 |
|
219 var iv = shape.map(function () { return 0; }); |
|
220 do { |
|
221 var e1 = a.get.apply(a, iv); |
|
222 var e2 = b.get.apply(b, iv); |
|
223 assertStructuralEq(e1, e2); |
|
224 } while (bump(iv)); |
|
225 } |