Skip to content

Explore seeds across worker processes - #15

Merged
dhruvl merged 1 commit into
mainfrom
parallel-explore
Jul 31, 2026
Merged

Explore seeds across worker processes#15
dhruvl merged 1 commit into
mainfrom
parallel-explore

Conversation

@dhruvl

@dhruvl dhruvl commented Jul 31, 2026

Copy link
Copy Markdown
Owner

explore(fn, seeds, jobs=N) and pytest --simloop-jobs=N fan seed batches out over a spawn-context ProcessPoolExecutor. The invariant is that parallelism never changes the answer: a batch frontier only accepts a failure once every batch that could contain an earlier seed has finished, so the reported seed is exactly the one a sequential sweep stops at — proven by unit tests over crafted completion orders plus an end-to-end agreement test.

Workers return positions and exception summaries only. The parent re-runs the failing seed (and the passing seed just below it, for the trace diff) to build the full report — which doubles as a cross-process replay check: a seed that does something different in the parent raises ParallelDeterminismError loudly.

Under pytest, workers import the test module by file path and unwrap the sim_test decoration; tests taking fixtures refuse parallel mode with a clear message rather than silently degrading. Workloads must be picklable for jobs>1, checked up front with an error that names the constraint.

Measured here (M4, 10 cores): the jobqueue 300-seed chaos campaign drops 5.5 s → 1.9 s under --simloop-jobs=8; a synthetic sweep does ~226 → ~598 seeds/s at 10 jobs. benchmarks/parallel.py reproduces the measurement; the numbers doc updates separately with the campaign results.

Sequential path is a pure refactor — determinism suite untouched and passing. 262 fast + 10 slow, mypy strict clean.

explore() takes jobs=N and pytest takes --simloop-jobs=N: seed batches
fan out over a spawn-context process pool, and a batch frontier makes
parallelism invisible in the answer — a failure only counts once every
batch that could hold an earlier one has finished, so the reported seed
is exactly the one a sequential sweep would have stopped at. Workers
send back positions and exception summaries, never traces; the parent
re-runs the failing seed (and the passing one below it) to build the
report, and a seed that behaves differently across processes raises a
determinism error instead of being papered over. Under pytest the
worker imports the test module by path and unwraps the decorated test;
tests that need fixtures refuse parallel mode by name. A benchmark
script measures the fan-out.
@dhruvl
dhruvl merged commit 6d82a1a into main Jul 31, 2026
4 checks passed
@dhruvl
dhruvl deleted the parallel-explore branch July 31, 2026 19:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant