Skip to content

Commit 5a9c119

Browse files
committed
test: drop the in-process cross-start-method seed test
test_seed_derivation_is_start_method_invariant started a multiprocessing pool in the shared pytest process, which intermittently left it in a state where the later off-screen (PyVista/VTK) rendering tests crashed with a bus error. It was the only non-slow test running a real pool in the integration suite. The property it checked -- the derivation is a pure function of a picklable root state, so it is start-method independent -- is already covered by the unit test (__child_seed equals root.spawn(n)[i] bit for bit). A real parallel run under spawn/forkserver, isolated in its own subprocess, is tracked in #1076. Signed-off-by: thc1006 <84045975+thc1006@users.noreply.github.com>
1 parent 3adc07a commit 5a9c119

1 file changed

Lines changed: 8 additions & 65 deletions

File tree

tests/integration/simulation/test_monte_carlo_determinism.py

Lines changed: 8 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -20,46 +20,25 @@
2020
not the stdlib ``random.choice``) and is covered directly in
2121
``tests/unit/stochastic/test_stochastic_model``.
2222
23-
Seed derivation being independent of the multiprocessing start method (fork,
24-
spawn or forkserver) is verified separately by
25-
``test_seed_derivation_is_start_method_invariant``, which uses a top-level
26-
picklable target so it is safe under ``spawn``/``forkserver`` -- unlike the
27-
``Flight``-stub test above, which reaches workers only under ``fork``.
23+
Seed derivation being independent of the multiprocessing start method is a
24+
property of the pure derivation helpers, unit tested in
25+
``tests/unit/simulation/test_monte_carlo_determinism`` (``__child_seed`` equals
26+
``root.spawn(n)[i]`` bit for bit). A full parallel run under ``spawn`` and
27+
``forkserver``, exercising the real ``multiprocess`` path rather than the
28+
helpers, is tracked in #1076; it needs to run its workers in an isolated
29+
subprocess, since starting a multiprocessing pool in this shared test process
30+
can destabilize the later off-screen rendering tests.
2831
"""
2932

3033
import json
31-
import multiprocessing
32-
from types import SimpleNamespace
3334

3435
import numpy as np
3536
import pytest
3637

3738
import rocketpy.simulation.monte_carlo as mc_module
3839
from rocketpy.simulation import MonteCarlo
39-
from rocketpy.simulation.monte_carlo import _seed_sequence_to_int
4040
from rocketpy.stochastic import StochasticRocket, StochasticSolidMotor
4141

42-
_child_seed = MonteCarlo._MonteCarlo__child_seed
43-
44-
45-
def _available_start_methods():
46-
"""The multiprocessing start methods this platform actually supports."""
47-
supported = multiprocessing.get_all_start_methods()
48-
return [method for method in ("fork", "spawn", "forkserver") if method in supported]
49-
50-
51-
def _derive_index_seeds(root_state, indices):
52-
"""Derive the per-index seed fingerprints from ``root_state``.
53-
54-
Top-level and picklable (only a small tuple and a list of ints cross the
55-
process boundary), so it runs unchanged under every start method -- including
56-
``spawn``/``forkserver``, which re-import this module rather than inheriting
57-
the parent's memory. It calls the real production helpers (``__child_seed``
58-
and ``_seed_sequence_to_int``) so the test tracks the shipped derivation.
59-
"""
60-
plan = SimpleNamespace(_MonteCarlo__root_state=root_state)
61-
return {index: _seed_sequence_to_int(_child_seed(plan, index)) for index in indices}
62-
6342

6443
class _StubFlight:
6544
"""Minimal stand-in for ``Flight`` that skips trajectory integration."""
@@ -236,39 +215,3 @@ def test_inputs_are_worker_invariant(
236215
for index in expected:
237216
assert serial[index] == par2[index], f"serial vs parallel(2) differ at {index}"
238217
assert serial[index] == par4[index], f"serial vs parallel(4) differ at {index}"
239-
240-
241-
@pytest.mark.parametrize("start_method", _available_start_methods())
242-
def test_seed_derivation_is_start_method_invariant(start_method):
243-
"""Per-index seeds derived in a worker match the main process under every
244-
available start method (fork, spawn, forkserver).
245-
246-
The full worker-invariance test above stubs the module-level ``Flight`` and so
247-
only reaches workers under ``fork``. This one instead checks the property that
248-
actually has to hold cross-platform -- that a simulation index maps to the same
249-
seed no matter which process derives it -- using a top-level picklable target
250-
and small picklable arguments, so it is valid under ``spawn``/``forkserver``
251-
(Python 3.14's POSIX default) without relying on any inherited parent state.
252-
Two workers split the indices; their combined result must equal the
253-
single-process derivation.
254-
"""
255-
root = np.random.SeedSequence(2718281828)
256-
root_state = (
257-
root.entropy,
258-
root.spawn_key,
259-
root.pool_size,
260-
root.n_children_spawned,
261-
)
262-
indices = list(range(6))
263-
expected = _derive_index_seeds(root_state, indices)
264-
265-
context = multiprocessing.get_context(start_method)
266-
chunks = [(root_state, indices[0::2]), (root_state, indices[1::2])]
267-
with context.Pool(2) as pool:
268-
results = pool.starmap(_derive_index_seeds, chunks)
269-
270-
combined = {}
271-
for result in results:
272-
combined.update(result)
273-
assert combined == expected
274-
assert sorted(combined) == indices

0 commit comments

Comments
 (0)