Context
PR #117's Curve B (test metric of the running incumbent) is reconstructed by re-evaluating each best-so-far changepoint config on the test set via final_eval. Today this re-eval is serial in a single process: it is launch-bound on the tiny datasets (one CPU core pegged, GPUs ~idle), and it writes its output JSON only at the very end (no checkpoint, so a killed run restarts from scratch). Because of the cost, Curve B is omitted for compas and loan (# re-eval = 0 in the docs saturation table).
Goal
Make the Curve-B re-eval (a) parallel across the device pool and (b) resumable, so it is ~10–20× faster and restartable — then regenerate compas and loan Curve B.
Where
benchmarks/_common/sensitivity_report.py:incumbent_test_curve — the serial per-incumbent final_eval loop (a per-incumbent progress log already exists via progress_label).
benchmarks/sensitivity.py — extract_dataset, _cmd_run.
benchmarks/_common/gpu_pool.py:fan_out — the shared work-stealing subprocess pool to reuse.
Proposed approach
Emit the independent incumbent re-evals (28 per dataset here; or per-(dataset,flavor)) as jobs and fan them across GPU slots via fan_out (oversubscribe — nets are ~0.7 GB). Memoize each incumbent's trial_idx → test IQM to a small cache file so a restart skips completed ones. Then run compas/loan and commit their curve JSONs + the updated figure.
Acceptance criteria
References
Context
PR #117's Curve B (test metric of the running incumbent) is reconstructed by re-evaluating each best-so-far changepoint config on the test set via
final_eval. Today this re-eval is serial in a single process: it is launch-bound on the tiny datasets (one CPU core pegged, GPUs ~idle), and it writes its output JSON only at the very end (no checkpoint, so a killed run restarts from scratch). Because of the cost, Curve B is omitted forcompasandloan(# re-eval = 0in the docs saturation table).Goal
Make the Curve-B re-eval (a) parallel across the device pool and (b) resumable, so it is ~10–20× faster and restartable — then regenerate
compasandloanCurve B.Where
benchmarks/_common/sensitivity_report.py:incumbent_test_curve— the serial per-incumbentfinal_evalloop (a per-incumbent progress log already exists viaprogress_label).benchmarks/sensitivity.py—extract_dataset,_cmd_run.benchmarks/_common/gpu_pool.py:fan_out— the shared work-stealing subprocess pool to reuse.Proposed approach
Emit the independent incumbent re-evals (28 per dataset here; or per-
(dataset,flavor)) as jobs and fan them across GPU slots viafan_out(oversubscribe — nets are ~0.7 GB). Memoize each incumbent'strial_idx → test IQMto a small cache file so a restart skips completed ones. Then runcompas/loanand commit their curve JSONs + the updated figure.Acceptance criteria
benchmarks/results/alternate-base/curves/{compas,loan}.jsoncontain Curve B; figure regenerated; docs "omitted for compas/loan" note removed.References
docs/benchmarks/hp-search-sensitivity.md("Follow-ups").