Repository navigation
fix: run numba prange kernels serially in multiprocessing search workers (#676) - #677
Merged
Merged
Conversation
…676) On numba's default GNU OpenMP threading layer, a child forked after the parent launched a parallel region is terminated ("fork() called from a process already using GNU OpenMP"). PyAutoFit evaluates the likelihood in the parent before forking Nautilus workers, so every DelaunayNN NumPy fit with number_of_cores > 1 died. Nested numba threads in each worker would also oversubscribe the node. - numba_util.parallel_kernel_allowed(): False in any multiprocessing child (parent_process() set) or a process whose pid differs from the first caller; function_copy() renames a function so one body can be cached under two compilations (numba's cache index ignores compile flags). - Sibson: one body compiled parallel=True and parallel=False; the NumPy dispatch picks via the predicate (identical outputs, tested). - direct_conv: _numba_parallel() is False in workers, which take the existing serial / symmetric route. - numba_util.jit warns once at materialization when general.yaml numba.parallel is True in a worker; the yaml comment says it is for single-process benchmarking only. - The threading layer and thread count are left untouched, so the single-process path is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The Sibson (DelaunayNN) numba kernel was always
parallel=True. Without TBB, numba's threading layer is GNU OpenMP, and its fork handler kills any forked child that launches a parallel region after the parent has used the pool. PyAutoFit evaluates the likelihood once in the parent before forking its search workers, so every NumPy-path DelaunayNN fit with more than one core failed withTerminating: fork() called from a process already using GNU OpenMP, this is unsafe.followed by a Nautilus poolTimeoutError. This was seen on RAL, job 414150, the likelihood-lifecycle phase 4 validation leg.Fix: numba parallel threads never run inside a Python multiprocessing worker. A new predicate,
numba_util.parallel_kernel_allowed(), is False in any multiprocessing child (fork, spawn or forkserver) and in a pid other than the one that first called it. In that case the Sibson dispatch uses aparallel=Falsecompilation of the same body, which gives identical results, and the interferometerdirect_convroute falls back to its existing serial or symmetric kernels. A single-process main process keeps the parallel kernel and numba's default threading layer, so profiled single-process performance is unchanged. This also stops the oversubscription where every worker started one numba thread per node core.Closes #676
API Changes
autoarray.numba_util.parallel_kernel_allowed()andautoarray.numba_util.function_copy()(internal helpers).sibson.sibson_numba_kernel()gainsparallel: bool = True; the default behaviour is unchanged.general.yamlnumba: parallelcomment: single-process benchmarking only, unsafe under multiprocessing searches.numba_util.jitlogs a one-time warning if it is True inside a worker.See full details below.
Test Plan
test_autoarray/test_numba_fork_safety.py(8 tests): a subprocess underNUMBA_THREADING_LAYER=ompruns the Sibson dispatch in the parent, then in fork and spawnPool(2)children, and the outputs must equal the parent's. It fails before the fix (4× "Terminating: fork()…", TimeoutError) and passes after. A control with the predicate forced True reproduces the termination. Serial output isarray_equalto parallel. There are unit tests of the predicate and of the worker route for_numba_parallel().pytest test_autoarray -x: 2295 passed, 4 xfailed, 0 failed (at head 56db9c0).omp, fork and spawn children running the serial build never initialise a threading layer.imaging/delaunay_nn/hstnumba_cpu_sparse validation leg (414150's submit) on a checkout carrying this fix; it should passsource_pix[1].Heart at ship: STALE, development pass. Reason: "release validation stale: source moved since rehearsal (PyAutoNerves)".
Full API Changes (for automation & release notes)
Removed
Added
autoarray.numba_util.parallel_kernel_allowed() -> bool: whether this process may launch a numbaprangekernel (False in multiprocessing children and forked pids).autoarray.numba_util.function_copy(func, name): a renamed copy of a plain function, so one body can be numba-compiled twice and both builds are cached on disk (numba's cache index key ignores compile flags).autoarray.inversion.mesh.interpolator._sibson_numba._sibson_from_tables_serial: theparallel=Falsecompilation of the Sibson body.Changed
sibson.sibson_numba_kernel(parallel=True): returns the parallel or serial build._sibson_mappings_weights_numbauses the serial build in search workers.interferometer_numba.sparse._numba_parallel()is False in search workers._sibson_from_tablesbody), so it recompiles once.Migration
Generated by the PyAutoLabs agent workflow.
🤖 Generated with Claude Code