Bug 856246 - Update test suite to consistently use minItemsTestingThreshold and other abstractions r=till

This commit is contained in:
Nicholas D. Matsakis 2013-06-07 06:32:17 -04:00
parent b6f59df383
commit 7620e77bff
33 changed files with 142 additions and 117 deletions

View File

@ -26,6 +26,7 @@
// (TODO: consider exposing numSlices via builtin/TestingFunctions.cpp)
var minItemsTestingThreshold = 1024;
var defaultStablizationAttempts = 5;
// The standard sequence of modes to test.
// First mode compiles for parallel exec.
@ -156,6 +157,41 @@ function assertEqParallelArray(a, b) {
} while (bump(iv));
}
// Helper for other functions. Iteratively attempts to compile and
// then execute `opFunction` in mode `mode` until either it has tried
// too many times or the execution succeeded. After each call, it will
// invoke `cmpFunction` with the result to validate we are producing
// correct output.
//
// Consider case where `mode` `par`: in that case, we are attempting
// to compile-and-run in succession until we either succeed at getting
// a complete run or we try too many times. This is useful because
// sometimes it takes a couple iterations for TI to stabilize, and
// using a loop with a threshold makes us less sensitive to
// pertubations that occur in TI inference.
function stabilize(opFunction, cmpFunction, mode, attempts) {
var failures = 0;
while (true) {
print("Attempting compile #", failures);
var result = opFunction({mode:"compile"});
cmpFunction(result);
try {
print("Attempting parallel run #", failures);
var result = opFunction({mode:mode});
cmpFunction(result);
break;
} catch (e) {
failures++;
if (failures > attempts) {
throw e; // doesn't seem to be reaching a fixed point!
} else {
print(e);
}
}
}
}
// Checks that whenever we execute this in parallel mode,
// it bails out. `opFunction` should be a closure that takes a
// mode parameter and performs some parallel array operation.
@ -170,8 +206,7 @@ function assertEqParallelArray(a, b) {
// where the `new ParallelArray(...)` is a stand-in
// for some parallel array operation.
function assertParallelExecWillBail(opFunction) {
opFunction({mode:"compile"}); // get the script compiled
opFunction({mode:"bailout"}); // check that it bails when executed
stabilize(opFunction, function() {}, "bailout", defaultStablizationAttempts);
}
// Checks that when we execute this in parallel mode,
@ -179,8 +214,7 @@ function assertParallelExecWillBail(opFunction) {
// return to parallel execution mode. `opFunction` is a closure
// that expects a mode, just as in `assertParallelExecWillBail`.
function assertParallelExecWillRecover(opFunction) {
opFunction({mode:"compile"}); // get the script compiled
opFunction({mode:"recover"}); // check that it bails when executed
stabilize(opFunction, function() {}, "recover", defaultStablizationAttempts);
}
// Checks that we will (eventually) be able to compile and exection
@ -190,27 +224,11 @@ function assertParallelExecWillRecover(opFunction) {
// `opFunction` with `compile` and then `par` mode until getting a
// successful `par` run. After enough tries, of course, we give up
// and declare a test failure.
function assertParallelExecSucceeds(opFunction, cmpFunction) {
var failures = 0;
while (true) {
print("Attempting compile #", failures);
var result = opFunction({mode:"compile"});
cmpFunction(result);
try {
print("Attempting parallel run #", failures);
var result = opFunction({mode:"par"});
cmpFunction(result);
break;
} catch (e) {
failures++;
if (failures > 5) {
throw e; // doesn't seem to be reaching a fixed point!
} else {
print(e);
}
}
}
function assertParallelExecSucceeds(opFunction,
cmpFunction,
attempts) {
attempts = attempts || defaultStablizationAttempts;
stabilize(opFunction, cmpFunction, "par", attempts);
print("Attempting sequential run");
var result = opFunction({mode:"seq"});
@ -267,7 +285,7 @@ function testScan(jsarray, func, cmpFunction) {
// In this case, because scatter is so complex, we do not attempt
// to compute the expected result and instead simply invoke
// `cmpFunction(r)` with the result `r` of the scatter operation.
function testScatter(opFunction, cmpFunction) {
function testScatter(opFunction, cmpFunction, attempts) {
var strategies = ["divide-scatter-version", "divide-output-range"];
for (var i in strategies) {
assertParallelExecSucceeds(
@ -277,7 +295,8 @@ function testScatter(opFunction, cmpFunction) {
print(JSON.stringify(m1));
return opFunction(m1);
},
cmpFunction);
cmpFunction,
attempts);
}
}

View File

@ -10,13 +10,13 @@ function makeObject(e, i, c) {
}
function test() {
var array = range(0, 768);
var array = range(0, minItemsTestingThreshold);
var array1 = array.map(makeObject);
assertParallelExecWillRecover(function (m) {
var pa = new ParallelArray(array);
var pa1 = pa.map(makeObject, m);
assertStructuralEq(pa1, array1);
// assertStructuralEq(pa1, array1);
});
}

View File

@ -14,4 +14,4 @@ function makeObject(e, i, c) {
}
if (getBuildConfiguration().parallelJS)
compareAgainstArray(range(0, 512), "map", makeObject);
compareAgainstArray(range(0, minItemsTestingThreshold), "map", makeObject);

View File

@ -14,11 +14,11 @@ function theTest() {
// run op once where it has to add doubles and strings,
// just to pullute the typesets:
var jsarray0 = range(0, 1024);
var jsarray0 = range(0, minItemsTestingThreshold);
jsarray0.map(op);
// this version will never actually touch the strings:
var jsarray1 = range(0, 1024).map(i => i % 10);
var jsarray1 = range(0, minItemsTestingThreshold).map(i => i % 10);
compareAgainstArray(jsarray1, "map", op);
// but if we try against the original we get bailouts:

View File

@ -1,16 +1,15 @@
load(libdir + "parallelarray-helpers.js");
function testClosureCreation() {
var a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9,10,
11,12,13,14,15,16,17,18,19,20,
21,22,23,24,25,26,27,28,29,30,
31,32,33,34,35,36,27,38,39,40];
var a = range(1, minItemsTestingThreshold+1);
var p = new ParallelArray(a);
var makeadd1 = function (v) { return function (x) { return x+1; }; };
for (var i in MODES) {
var m = p.map(makeadd1, MODES[i]);
assertEq(m.get(1)(2), 3); // (\x.x+1) 2 == 3
}
assertParallelExecSucceeds(
function(m) p.map(makeadd1, m),
function(r) {
assertEq(r.get(1)(2), 3); // (\x.x+1) 2 == 3
}
);
}
if (getBuildConfiguration().parallelJS)

View File

@ -1,14 +0,0 @@
load(libdir + "parallelarray-helpers.js");
function testClosureCreation() {
var a = range(0, 64);
var p = new ParallelArray(a);
var makeadd1 = function (v) { return function (x) { return x+1; }; };
for (var i in MODES) {
var m = p.map(makeadd1, MODES[i]);
assertEq(m.get(1)(2), 3); // (\x.x+1) 2 == 3
}
}
if (getBuildConfiguration().parallelJS)
testClosureCreation();

View File

@ -1,14 +1,10 @@
load(libdir + "parallelarray-helpers.js");
function testClosureCreationAndInvocation() {
var a = range(1, 65);
var p = new ParallelArray(a);
var a = range(1, minItemsTestingThreshold+1);
function etaadd1(v) { return (function (x) { return x+1; })(v); };
// eta-expansion is (or at least can be) treated as call with unknown target
for (var i in MODES) {
var m = p.map(etaadd1, MODES[i]);
assertEq(m.get(1), 3); // (\x.x+1) 2 == 3
}
compareAgainstArray(a, "map", etaadd1);
}
if (getBuildConfiguration().parallelJS)

View File

@ -1,14 +1,15 @@
load(libdir + "parallelarray-helpers.js");
function testClosureCreationAndInvocation() {
var a = range(1, 65);
var a = range(1, minItemsTestingThreshold+1);
var p = new ParallelArray(a);
function makeaddv(v) { return function (x) { return x+v; }; };
for (var i in MODES) {
var m = p.map(makeaddv, MODES[i]);
assertEq(m.get(1)(1), 3); // (\x.x+v){v=2} 1 == 3
assertEq(m.get(2)(2), 5); // (\x.x+v){v=3} 2 == 5
}
assertParallelExecSucceeds(
function(m) p.map(makeaddv, m),
function(r) {
assertEq(r.get(1)(1), 3); // (\x.x+v){v=2} 1 == 3
assertEq(r.get(2)(2), 5); // (\x.x+v){v=3} 2 == 5
});
}
if (getBuildConfiguration().parallelJS)

View File

@ -1,7 +1,7 @@
load(libdir + "parallelarray-helpers.js");
function testClosureCreationAndInvocation() {
var a = range(1, 65);
var a = range(1, minItemsTestingThreshold+1);
var p = new ParallelArray(a);
function makeaddv(v) {
var u = v - 1;

View File

@ -1,7 +1,7 @@
load(libdir + "parallelarray-helpers.js");
function testClosureCreationAndInvocation() {
var a = range(0, 64);
var a = range(0, minItemsTestingThreshold);
var p = new ParallelArray(a);
function makeaddv(v) {
var u = v - 1;

View File

@ -1,7 +1,7 @@
load(libdir + "parallelarray-helpers.js");
function testClosureCreationAndInvocation() {
var a = range(0, 64);
var a = range(0, minItemsTestingThreshold);
var p = new ParallelArray(a);
function makeaddv(v) {
var u = 1;
@ -41,10 +41,12 @@ function testClosureCreationAndInvocation() {
}
};
};
for (var i in MODES) {
var m = p.map(makeaddv, MODES[i]);
assertEq(m.get(21)(1), 20); // v == 21; x == 1 ==> inner function returns b == 20
}
assertParallelExecSucceeds(
function(m) p.map(makeaddv, m),
function(r) {
assertEq(r.get(21)(1), 20); // v == 21; x == 1 ==> inner function returns b == 20
}
);
}
if (getBuildConfiguration().parallelJS)

View File

@ -1,7 +1,7 @@
load(libdir + "parallelarray-helpers.js");
function testClosureCreationAndInvocation() {
var a = range(0, 64);
var a = range(0, minItemsTestingThreshold);
var p = new ParallelArray(a);
function makeaddv(v) {
var u = 1;
@ -43,12 +43,20 @@ function testClosureCreationAndInvocation() {
}
});
}
var m;
for (var i in MODES) m = p.map(makeaddv, MODES[i]);
assertEq(m.get(21)(1), 20); // v == 21; x == 1 ==> inner function returns b == 20
var n = p.map(function (v) { return function (x) { return v; }});
assertEq(n.get(21)(1), 21); // v == 21
assertParallelExecSucceeds(
function(m) p.map(makeaddv, m),
function(r) {
assertEq(r.get(21)(1), 20); // v == 21; x == 1 ==> inner function returns b == 20
}
);
assertParallelExecSucceeds(
function(m) p.map(function (v) { return function (x) { return v; }}),
function(r) {
assertEq(r.get(21)(1), 21); // v == 21
}
);
}
if (getBuildConfiguration().parallelJS)

View File

@ -6,7 +6,7 @@ load(libdir + "parallelarray-helpers.js");
// equality but not loose equality.
function theTest() {
var ints = range(0, 1024);
var ints = range(0, minItemsTestingThreshold);
var doubles = ints.map(v => v + 0.1);
var bools = ints.map(v => (v % 2) == 0);
var strings = ints.map(v => String(v));

View File

@ -1,3 +1,4 @@
load(libdir + "parallelarray-helpers.js");
if (getBuildConfiguration().parallelJS)
compareAgainstArray(range(0, 1024), "filter", function() { return true; });
compareAgainstArray(range(0, minItemsTestingThreshold), "filter",
function() { return true; });

View File

@ -1,6 +1,5 @@
load(libdir + "parallelarray-helpers.js");
if (getBuildConfiguration().parallelJS)
compareAgainstArray(range(0, 1024), "filter", function(e, i) {
return (i % 3) != 0;
});
compareAgainstArray(range(0, minItemsTestingThreshold), "filter",
function(e, i) { return (i % 3) != 0; });

View File

@ -4,4 +4,5 @@ load(libdir + "parallelarray-helpers.js");
// bitsets, test that all that logic works fine if the number of items
// is not evenly divisible by 32:
if (getBuildConfiguration().parallelJS)
compareAgainstArray(range(0, 617), "filter", function(i) { return (i % 2) == 0; });
compareAgainstArray(range(0, minItemsTestingThreshold+17), "filter",
function(i) { return (i % 2) == 0; });

View File

@ -1,3 +1,4 @@
load(libdir + "parallelarray-helpers.js");
if (getBuildConfiguration().parallelJS)
compareAgainstArray(range(0, 1024), "filter", function() { return false; });
compareAgainstArray(range(0, minItemsTestingThreshold), "filter",
function() { return false; });

View File

@ -12,7 +12,7 @@ function testFilterMisc() {
}
}
compareAgainstArray(range(0, 1024), "filter", truthy);
compareAgainstArray(range(0, minItemsTestingThreshold), "filter", truthy);
}
if (getBuildConfiguration().parallelJS)

View File

@ -1,3 +1,3 @@
load(libdir + "parallelarray-helpers.js");
if (getBuildConfiguration().parallelJS)
compareAgainstArray(range(0, 1024), "filter", function(i) { return i <= 1 || i >= 1022; });
compareAgainstArray(range(0, minItemsTestingThreshold), "filter", function(i) { return i <= 1 || i >= 1022; });

View File

@ -1,6 +1,6 @@
load(libdir + "parallelarray-helpers.js");
var SIZE = 4096;
var SIZE = minItemsTestingThreshold;
function testMap() {
var q = {f: 22};

View File

@ -6,4 +6,5 @@ function factorial(n) {
return n * factorial(n - 1);
}
if (getBuildConfiguration().parallelJS) compareAgainstArray(range(0, 64), "map", factorial);
if (getBuildConfiguration().parallelJS)
compareAgainstArray(range(0, minItemsTestingThreshold), "map", factorial);

View File

@ -1,20 +1,21 @@
load(libdir + "parallelarray-helpers.js")
function test() {
var pa0 = new ParallelArray(range(0, 256));
var pa0 = new ParallelArray(range(0, minItemsTestingThreshold));
var pa1;
for (var i in MODES)
pa1 = new ParallelArray(256, function (x) {
assertParallelExecSucceeds(
function(m) new ParallelArray(minItemsTestingThreshold, function (x) {
return pa0.map(function(y) { return x * 1000 + y; });
}, MODES[i]);
for (var x = 0; x < 256; x++) {
var pax = pa1.get(x);
for (var y = 0; y < 256; y++) {
assertEq(pax.get(y), x * 1000 + y);
}
}
}, m),
function(pa1) {
for (var x = 0; x < minItemsTestingThreshold; x++) {
var pax = pa1.get(x);
for (var y = 0; y < minItemsTestingThreshold; y++) {
assertEq(pax.get(y), x * 1000 + y);
}
}
});
}
if (getBuildConfiguration().parallelJS) test();
if (getBuildConfiguration().parallelJS)
test();

View File

@ -6,4 +6,5 @@ function wrapInObject(v) {
return obj;
}
if (getBuildConfiguration().parallelJS) compareAgainstArray(range(0, 64), "map", wrapInObject);
if (getBuildConfiguration().parallelJS)
compareAgainstArray(range(0, minItemsTestingThreshold), "map", wrapInObject);

View File

@ -3,9 +3,14 @@ load(libdir + "parallelarray-helpers.js");
function test() {
// Test what happens if the length of the array is very short (i.e.,
// less than the number of cores). There used to be a bug in this
// case that led to crashes or other undefined behavior.
// case that led to crashes or other undefined behavior. Note that
// we don't necessarily expected this to *parallelize*.
var makeadd1 = function (v) { return [v]; }
compareAgainstArray(range(1, 3), "map", makeadd1);
var array = range(1, 3);
var expected = array.map(makeadd1);
var actual = new ParallelArray(array).map(makeadd1);
assertStructuralEq(expected, actual);
}
if (getBuildConfiguration().parallelJS) test();
if (getBuildConfiguration().parallelJS)
test();

View File

@ -2,7 +2,7 @@ load(libdir + "parallelarray-helpers.js");
function testReduce() {
// Test reduce elemental fun args
var N = 64;
var N = minItemsTestingThreshold;
var p = new ParallelArray(range(1, N+1));
var r = p.reduce(function (a, b) {
assertEq(a >= 1 && a <= N, true);

View File

@ -8,7 +8,8 @@ function testReduce() {
function mul(v, p) { return v*p; }
// Ensure that the array only contains values between 1 and 4.
var array = range(1, 513).map(function(v) { return (v % 4) + 1; });
var array = range(1, minItemsTestingThreshold+1).map(
function(v) { return (v % 4) + 1; });
compareAgainstArray(array, "reduce", mul, assertAlmostEq);
}

View File

@ -7,7 +7,7 @@ function testReduce() {
// where the non-commutative of floating point becomes relevant,
// so we must use assertAlmostEq.
function mul(v, p) { return v*p; }
var array = range(1, 513);
var array = range(1, minItemsTestingThreshold+1);
compareAgainstArray(array, "reduce", mul, assertAlmostEq);
}

View File

@ -2,7 +2,7 @@ load(libdir + "parallelarray-helpers.js");
function testReduce() {
function sum(v, p) { return v+p; }
compareAgainstArray(range(1, 513), "reduce", sum);
compareAgainstArray(range(1, minItemsTestingThreshold+1), "reduce", sum);
}
if (getBuildConfiguration().parallelJS) testReduce();

View File

@ -1,3 +1,4 @@
load(libdir + "parallelarray-helpers.js");
function sum(a, b) { return a+b; }
if (getBuildConfiguration().parallelJS) testScan(range(1, 1024), sum);
if (getBuildConfiguration().parallelJS)
testScan(range(0, minItemsTestingThreshold), sum);

View File

@ -7,7 +7,7 @@ load(libdir + "parallelarray-helpers.js");
// [A, B, C, D, ..., W, X, Y, Z] ==> [Z+Y, X, W, ..., D, C, B+A]
function testDivideScatterVector() {
var len = 1024;
var len = minItemsTestingThreshold;
function add1(x) { return x+1; }
function add3(x) { return x+3; }
function id(x) { return x; }
@ -21,4 +21,5 @@ function testDivideScatterVector() {
r => assertEqParallelArray(r, expect));
}
if (getBuildConfiguration().parallelJS) testDivideScatterVector();
if (getBuildConfiguration().parallelJS)
testDivideScatterVector();

View File

@ -9,7 +9,7 @@ function kernel(n) {
}
function testMap() {
var p = new ParallelArray(range(0, 2048));
var p = new ParallelArray(range(0, minItemsTestingThreshold));
assertParallelExecWillBail(
m => p.map(kernel, m));
}

View File

@ -7,7 +7,7 @@ function test() {
throw x;
return n + 1;
}
var x = new ParallelArray(range(0, 2048));
var x = new ParallelArray(range(0, minItemsTestingThreshold));
assertParallelExecWillBail(
m => x.map(inc, m));

View File

@ -6,4 +6,5 @@ function inc(n) {
return n + 1;
}
if (getBuildConfiguration().parallelJS) compareAgainstArray(range(0, 512), "map", inc);
if (getBuildConfiguration().parallelJS)
compareAgainstArray(range(0, minItemsTestingThreshold), "map", inc);