Skip to content

Instantly share code, notes, and snippets.

@miyaokamarina
Last active October 23, 2023 11:04
Show Gist options
  • Save miyaokamarina/2da5f784fde9c9f8924f60b4475f14f6 to your computer and use it in GitHub Desktop.
Save miyaokamarina/2da5f784fde9c9f8924f60b4475f14f6 to your computer and use it in GitHub Desktop.
Running TestU01 BigCrush in parallel
// The worker binary.
// Compile as
// gcc -Wall -O3 -o ./OUT_DIR/tu01 ./tu01.c
// -Iinclude -Llib -ltestu01 -lprobdist -lmylib -lm
#include <TestU01.h>
// Should provide:
// • void reset(); -- Init/reset the state.
// • uint32_t fwd(); -- Generate random u32, normal bit order.
// • uint32_t rev(); -- Generate random u32, reverse bit order.
#include "my-prng.h"
int main(int argc, char **argv) {
swrite_Basic = false;
bool reverse = false;
uint32_t test = 0;
uint32_t runs = 0;
int32_t rep[107] = {};
while (1) {
argc--;
argv++;
if (argc == 0)
break;
switch (argv[0][1]) {
case 'r': // Reverse bits
reverse = true;
break;
case 't': // Test #
argc--;
argv++;
sscanf(argv[0], "%d", &test);
break;
case 'n': // Runs of the test
argc--;
argv++;
sscanf(argv[0], "%d", &runs);
break;
case 'v': // Verbose
swrite_Basic = true;
break;
}
}
rep[test] = runs;
reset(); // Init/reset the state of RNG
unif01_Gen *gen = reverse
? unif01_CreateExternGenBits("My PRNG [Reverse]", rev)
: unif01_CreateExternGenBits("My PRNG [Forward]", fwd);
bbattery_RepeatBigCrush(gen, rep);
unif01_DeleteExternGenBits(gen);
return 0;
}
// @ts-check
// The scheduler srcipt.
import { spawn } from 'node:child_process';
// Compiled binary name:
const BIN = './tmp/tu01';
// Repeat each test N times.
const N = 3;
// Run tests ## [MIN, MAX] (inclusive).
// To run single test, set MIN = MAX.
const MIN_TEST = 1;
const MAX_TEST = 106;
const main = () => {
// Number of processes to spawn.
// Set to the number of CPUs/threads or whatever you want.
let active = 8;
/** @type {Task[]} */
let queue = [];
// • Fill the queue.
for (let test = MIN_TEST; test <= MAX_TEST; test++) {
queue.push({ test, reverse: true });
queue.push({ test, reverse: false });
}
// • Adjust the number of workers.
active = Math.min(active, queue.length);
// • Pull a task.
// • Run it.
// • Handle its finish.
// • Also handle the queue finish.
const enqueue = () => {
let task = queue.shift();
// No tasks left:
if (!task) active--;
// The last task is finished:
if (active === 0) {
for (let i = MIN_TEST; i <= MAX_TEST; i++) {
let p = pad3(i);
report(`${p}-0`);
report(`${p}-1`);
}
return;
}
if (!task) return;
let a = performance.now();
console.error(
'[RUNNING] Test#%o %o [%s]',
task.test,
BIG_CRUSH_NAMES[task.test],
task.reverse ? 'Reverse' : 'Forward',
);
run(task).then(({ task, stdout, stderr, status }) => {
let b = performance.now();
let time = b - a;
let pass = stdout.endsWith('All tests were passed');
console.error(
'%s Test#%o %o [%s] in %os',
pass ? '[OK] ' : '[FAILED] ',
task.test,
BIG_CRUSH_NAMES[task.test],
task.reverse ? 'Reverse' : 'Forward',
Math.round(time / 1000),
);
reports.set(`${pad3(task.test)}-${Number(task.reverse)}`, {
test: task.test,
reverse: task.reverse,
stdout,
stderr,
status,
time,
pass,
});
enqueue();
});
};
// • Spawn workers.
for (let i = 0; i < active; i++) {
enqueue();
}
};
/**
* @typedef {object} Report
* @prop {number} test
* @prop {boolean} reverse
* @prop {string} stdout
* @prop {string} stderr
* @prop {number} status
* @prop {number} time
* @prop {boolean} pass
*
* @typedef {object} Task
* @prop {number} test
* @prop {boolean} reverse
*
* @typedef {object} Output
* @prop {Task} task
* @prop {string} stdout
* @prop {string} stderr
* @prop {number} status
*/
/** @type {Map<string, Report>} */
let reports = new Map();
/** @param {Task} task */
const run = task => {
return /** @type {Promise<Output>} */ (
new Promise((resolve, reject) => {
/** @type {string[]} */
let args = ['-t', String(task.test), '-n', String(N)];
if (task.reverse) args.push('-r');
let proc = spawn(BIN, args);
let stdout = [];
let stderr = [];
let settled = false;
proc.stdout.on('data', chunk => stdout.push(chunk));
proc.stderr.on('data', chunk => stderr.push(chunk));
proc.on('close', status => {
if (settled) return;
settled = true;
resolve({
task,
stdout: trim(stdout.join('')),
stderr: trim(stderr.join('')),
status: status ?? 0,
});
});
proc.on('error', error => {
if (settled) return;
settled = true;
reject(error);
});
})
);
};
/** @param {string} k */
const report = k => {
let report = reports.get(k);
if (!report) return;
let { test, reverse, stdout, stderr, status, time, pass } = report;
console.log([test, BIG_CRUSH_NAMES[test], reverse, pass, time, status].join(','));
console.log('# stdout');
console.log(indent(stdout));
console.log('# stderr');
console.log(indent(stderr));
};
/** @param {number} n */
const pad3 = n => n.toString().padStart(3, '0');
/** @param {string} s */
const trim = s => {
return s
.trim()
.split('\n')
.map(x => x.trimEnd())
.join('\n')
.replace(/\n\n+/g, '\n');
};
/** @param {string} s */
const indent = s => {
return trim(
s
.split('\n')
.map(x => '# -- ' + x)
.join('\n'),
);
};
const BIG_CRUSH_NAMES = [
null,
'smarsa_SerialOver with N = 1, n = 10⁹, r = 0, d = 2⁸, t = 3',
'smarsa_SerialOver with N = 1, n = 10⁹, r = 22, d = 2⁸, t = 3',
'smarsa_CollisionOver with N = 30, n = 2×10⁷, r = 0, d = 2²¹, t = 2',
'smarsa_CollisionOver with N = 30, n = 2×10⁷, r = 9, d = 2²¹, t = 2',
'smarsa_CollisionOver with N = 30, n = 2×10⁷, r = 0, d = 2¹⁴, t = 3',
'smarsa_CollisionOver with N = 30, n = 2×10⁷, r = 16, d = 2¹⁴, t = 3',
'smarsa_CollisionOver with N = 30, n = 2×10⁷, r = 0, d = 2⁶, t = 7',
'smarsa_CollisionOver with N = 30, n = 2×10⁷, r = 24, d = 2⁶, t = 7',
'smarsa_CollisionOver with N = 30, n = 2×10⁷, r = 0, d = 2³, t = 14',
'smarsa_CollisionOver with N = 30, n = 2×10⁷, r = 27, d = 2³, t = 14',
'smarsa_CollisionOver with N = 30, n = 2×10⁷, r = 0, d = 2², t = 21',
'smarsa_CollisionOver with N = 30, n = 2×10⁷, r = 28, d = 2², t = 21',
'smarsa_BirthdaySpacings with N = 100, n = 1×10⁷, r = 0, d = 2³¹, t = 2, p = 1',
'smarsa_BirthdaySpacings with N = 20, n = 2×10⁷, r = 0, d = 2²¹, t = 3, p = 1',
'smarsa_BirthdaySpacings with N = 20, n = 3×10⁷, r = 14, d = 2¹⁶, t = 4, p = 1',
'smarsa_BirthdaySpacings with N = 20, n = 2×10⁷, r = 0, d = 2⁹, t = 7, p = 1',
'smarsa_BirthdaySpacings with N = 20, n = 2×10⁷, r = 7, d = 2⁹, t = 7, p = 1',
'smarsa_BirthdaySpacings with N = 20, n = 3×10⁷, r = 14, d = 2⁸, t = 8, p = 1',
'smarsa_BirthdaySpacings with N = 20, n = 3×10⁷, r = 22, d = 2⁸, t = 8, p = 1',
'smarsa_BirthdaySpacings with N = 20, n = 3×10⁷, r = 0, d = 2⁴, t = 16, p = 1',
'smarsa_BirthdaySpacings with N = 20, n = 3×10⁷, r = 26, d = 2⁴, t = 16, p = 1',
'snpair_ClosePairs with N = 30, n = 6×10⁶, r = 0, t = 3, p = 0, m = 30',
'snpair_ClosePairs with N = 20, n = 4×10⁶, r = 0, t = 5, p = 0, m = 30',
'snpair_ClosePairs with N = 10, n = 3×10⁶, r = 0, t = 9, p = 0, m = 30',
'snpair_ClosePairs with N = 5, n = 2×10⁶, r = 0, t = 16, p = 0, m = 30',
'sknuth_SimpPoker with N = 1, n = 4×10⁸, r = 0, d = 8, k = 8',
'sknuth_SimpPoker with N = 1, n = 4×10⁸, r = 27, d = 8, k = 8',
'sknuth_SimpPoker with N = 1, n = 1×10⁸, r = 0, d = 32, k = 32',
'sknuth_SimpPoker with N = 1, n = 1×10⁸, r = 25, d = 32, k = 32',
'sknuth_CouponCollector with N = 1, n = 2×10⁸, r = 0, d = 8',
'sknuth_CouponCollector with N = 1, n = 2×10⁸, r = 10, d = 8',
'sknuth_CouponCollector with N = 1, n = 2×10⁸, r = 20, d = 8',
'sknuth_CouponCollector with N = 1, n = 2×10⁸, r = 27, d = 8',
'sknuth_Gap with N = 1, n = 5×10⁸, r = 0, α = 0, β = 1⁄2⁴',
'sknuth_Gap with N = 1, n = 3×10⁸, r = 25, α = 0, β = 1⁄2⁵',
'sknuth_Gap with N = 1, n = 1×10⁸, r = 0, α = 0, β = 1⁄2⁷',
'sknuth_Gap with N = 1, n = 1×10⁷, r = 20, α = 0, β = 1⁄2¹⁰',
'sknuth_Run with N = 5, n = 10⁹, r = 0, ↑ = false',
'sknuth_Run with N = 5, n = 10⁹, r = 15, ↑ = true',
'sknuth_Permutation with N = 1, n = 1×10⁹, r = 0, t = 3',
'sknuth_Permutation with N = 1, n = 1×10⁹, r = 0, t = 5',
'sknuth_Permutation with N = 1, n = 5×10⁸, r = 0, t = 7',
'sknuth_Permutation with N = 1, n = 5×10⁸, r = 10, t = 10',
'sknuth_CollisionPermut with N = 20, n = 2×10⁷, r = 0, t = 14',
'sknuth_CollisionPermut with N = 20, n = 2×10⁷, r = 10, t = 14',
'sknuth_MaxOft with N = 40, n = 10⁷, r = 0, d = 10⁵, t = 8',
'sknuth_MaxOft with N = 30, n = 10⁷, r = 0, d = 10⁵, t = 16',
'sknuth_MaxOft with N = 20, n = 10⁷, r = 0, d = 10⁵, t = 24',
'sknuth_MaxOft with N = 20, n = 10⁷, r = 0, d = 10⁵, t = 32',
'svaria_SampleProd with N = 40, n = 10⁷, r = 0, t = 8',
'svaria_SampleProd with N = 20, n = 10⁷, r = 0, t = 16',
'svaria_SampleProd with N = 20, n = 10⁷, r = 0, t = 24',
'svaria_SampleMean with N = 2×10⁷, n = 30, r = 0',
'svaria_SampleMean with N = 2×10⁷, n = 30, r = 10',
'svaria_SampleCorr with N = 1, n = 2×10⁹, r = 0, k = 1',
'svaria_SampleCorr with N = 1, n = 2×10⁹, r = 0, k = 2',
'svaria_AppearanceSpacings with N = 1, Q = 10⁷, K = 10⁹, r = 0, s = 3, L = 15',
'svaria_AppearanceSpacings with N = 1, Q = 10⁷, K = 10⁹, r = 27, s = 3, L = 15',
'svaria_WeightDistrib with N = 1, n = 2×10⁷, r = 0, k = 2⁸, α = 0, β = 1⁄2²',
'svaria_WeightDistrib with N = 1, n = 2×10⁷, r = 20, k = 2⁸, α = 0, β = 1⁄2²',
'svaria_WeightDistrib with N = 1, n = 2×10⁷, r = 28, k = 2⁸, α = 0, β = 1⁄2²',
'svaria_WeightDistrib with N = 1, n = 2×10⁷, r = 0, k = 2⁸, α = 0, β = 1⁄2⁴',
'svaria_WeightDistrib with N = 1, n = 2×10⁷, r = 10, k = 2⁸, α = 0, β = 1⁄2⁴',
'svaria_WeightDistrib with N = 1, n = 2×10⁷, r = 26, k = 2⁸, α = 0, β = 1⁄2⁴',
'svaria_SumCollector with N = 1, n = 5×10⁸, r = 0, g = 10',
'smarsa_MatrixRank with N = 10, n = 10⁶, r = 0, s = 5, L = k = 30',
'smarsa_MatrixRank with N = 10, n = 10⁶, r = 25, s = 5, L = k = 30',
'smarsa_MatrixRank with N = 1, n = 5000, r = 0, s = 4, L = k = 1000',
'smarsa_MatrixRank with N = 1, n = 5000, r = 26, s = 4, L = k = 1000',
'smarsa_MatrixRank with N = 1, n = 80, r = 15, s = 15, L = k = 5000',
'smarsa_MatrixRank with N = 1, n = 80, r = 0, s = 30, L = k = 5000',
'smarsa_Savir2 with N = 10, n = 10⁷, r = 10, m = 2²⁰, t = 30',
'smarsa_GCD with N = 10, n = 5×10⁷, r = 0, s = 30',
'swalk_RandomWalk1 with N = 1, n = 10⁸, r = 0, s = 5, L0 = L1 = 50',
'swalk_RandomWalk1 with N = 1, n = 10⁸, r = 25, s = 5, L0 = L1 = 50',
'swalk_RandomWalk1 with N = 1, n = 10⁷, r = 0, s = 10, L0 = L1 = 1000',
'swalk_RandomWalk1 with N = 1, n = 10⁷, r = 20, s = 10, L0 = L1 = 1000',
'swalk_RandomWalk1 with N = 1, n = 10⁶, r = 0, s = 15, L0 = L1 = 10000',
'swalk_RandomWalk1 with N = 1, n = 10⁶, r = 15, s = 15, L0 = L1 = 10000',
'scomp_LinearComp with N = 1, n = 400000, r = 0, s = 1',
'scomp_LinearComp with N = 1, n = 400000, r = 29, s = 1',
'scomp_LempelZiv with N = 10, k = 27, r = 0, s = 30',
'scomp_LempelZiv with N = 10, k = 27, r = 15, s = 15',
'sspectral_Fourier3 with N = 100000, r = 0, s = 3, k = 14',
'sspectral_Fourier3 with N = 100000, r = 27, s = 3, k = 14',
'sstring_LongestHeadRun with N = 1, n = 1000, r = 0, s = 3, L = 10⁷',
'sstring_LongestHeadRun with N = 1, n = 1000, r = 27, s = 3, L = 10⁷',
'sstring_PeriodsInStrings with N = 10, n = 5×10⁸, r = 0, s = 10',
'sstring_PeriodsInStrings with N = 10, n = 5×10⁸, r = 20, s = 10',
'sstring_HammingWeight2 with N = 10, n = 10⁹, r = 0, s = 3, L = 10⁶',
'sstring_HammingWeight2 with N = 10, n = 10⁹, r = 27, s = 3, L = 10⁶',
'sstring_HammingCorr with N = 1, n = 10⁹, r = 10, s = 10, L = 30',
'sstring_HammingCorr with N = 1, n = 10⁸, r = 10, s = 10, L = 300',
'sstring_HammingCorr with N = 1, n = 10⁸, r = 10, s = 10, L = 1200',
'sstring_HammingIndep with N = 10, n = 3×10⁷, r = 0, s = 3, L = 30, d = 0',
'sstring_HammingIndep with N = 10, n = 3×10⁷, r = 27, s = 3, L = 30, d = 0',
'sstring_HammingIndep with N = 1, n = 3×10⁷, r = 0, s = 4, L = 300, d = 0',
'sstring_HammingIndep with N = 1, n = 3×10⁷, r = 26, s = 4, L = 300, d = 0',
'sstring_HammingIndep with N = 1, n = 1×10⁷, r = 0, s = 5, L = 1200, d = 0',
'sstring_HammingIndep with N = 1, n = 1×10⁷, r = 25, s = 5, L = 1200, d = 0',
'sstring_Run with N = 1, n = 2×10⁹, r = 0, s = 3',
'sstring_Run with N = 1, n = 2×10⁹, r = 27, s = 3',
'sstring_AutoCor with N = 10, n = 10⁹, r = 0, s = 3, d = 1',
'sstring_AutoCor with N = 10, n = 10⁹, r = 0, s = 3, d = 3',
'sstring_AutoCor with N = 10, n = 10⁹, r = 27, s = 3, d = 1',
'sstring_AutoCor with N = 10, n = 10⁹, r = 27, s = 3, d = 3',
];
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment