Repository navigation
feat: finufft as the CPU NUFFT backend (JAX-free NumPy interferometer runs) - #655
Merged
Merged
Conversation
…654) TransformerNUFFT (forward, adjoint, mapping-matrix transform) and the NUFFT precision-operator / sparse-terms builders use finufft on the NumPy path, so a use_jax=False interferometer run never imports nufftax or starts JAX. use_jax now selects the operator builder backend. finufft is a platform-marked core dependency with a nufftax fallback; forked children are pinned to one finufft thread to avoid a libgomp fork deadlock. 25-35x faster than nufftax on CPU, agreeing to ~1e-14. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013C7Zd6ibK9J4V8CFEUzrJU
…re reproducible A multithreaded type-1 spread sums thread subgrids in a non-deterministic order, so two identical precision-operator / dirty-image builds differed in the last bits (13 bitwise-equality tests failed with OMP threads > 1; CI py3.13 red). These are one-off precomputations; one thread is ~0.9 s for 5.5M visibilities, still ~10x faster than nufftax, and the likelihood never uses this transform. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013C7Zd6ibK9J4V8CFEUzrJU
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
TransformerNUFFTand the NUFFT precision-operator builder now use finufft (CPU C++ NUFFT, NumPy API) on the NumPy path and keep nufftax for the JAX path. Ause_jax=Falseinterferometer run no longer imports nufftax or starts JAX at all.Why: every eager NumPy NUFFT (the dirty image in
apply_sparse_operator, the precision operator,visibilities_fromfor fits and visualisation) went through nufftax, so a NumPy/numba run silently started JAX and paid JAX's eager cost. On a collaborator's ALMA dataset (5.5M visibilities, 125×125 mask, eps 1e-12; RAL EPYC 7763, 8 threads):visibilities_fromEnd to end on RAL with this branch, that collaborator's preprocessing took 2.4 s (was ~20 s and a ~44 GB unchunked peak).
Note: an earlier draft of #654 attributed a ≥16-worker Nautilus segfault to JAX. That was wrong: it persists with JAX blocked from import. The real cause (numba first imported inside forked workers) is fixed in the companion PyAutoFit PR. This PR stands on speed, memory and JAX-free NumPy runs.
Closes #654 (together with the PyAutoFit PR).
API Changes
finufft>=2.4.0(platform-marked to wheels: Linux/Windows x86_64, macOS arm64; Intel macOS capped<2.5). Elsewhere (e.g. Linux aarch64) the NumPy path falls back to nufftax with a one-time warning.psf_precision_operator_from(use_jax=...)/nufft_precision_operator_from(method="nufft", use_jax=...):use_jaxnow selects the backend (False = finufft default, True = nufftax). It was documented as ignored.PYAUTO_DISABLE_JAXno longer demotes the default NUFFT builder to the brute force (finufft is not JAX).xp=jnppaths are unchanged (jit / vmap / grad keep using nufftax).See full details below.
Test Plan
pytest test_autoarray: 2191 passed, 4 xfailed (also withOMP_NUM_THREADSunset, i.e. multithreaded)pyauto-heart smoke, worktree root): 165/165 pass across autofit, autogalaxy, autolens, autolens_workspace_test, euclid pipeline, HowToLens; autocti envs failedarcticpyinstall before running (unrelated)image_from/visibilities_from/transform_mapping_matrix(chunked/unchunked, ± primary beam); operator vs NumPy brute force and vsuse_jax=Trueapply_sparse_operator, forward, adjoint, mapping-matrix transform) never imports nufftax or starts XLAFull API Changes (for automation & release notes)
Added
autoarray.operators.nufft_cpu—nufft2d1(x, y, c, n_modes, eps, isign),nufft2d2(x, y, f, eps, isign)(nufftax signature and orientation, finufft-backed, nufftax fallback),backend_available(),nufft_cpu_exception()._type1_real_grid_from(..., use_jax=False)backend switch (internal).Changed
TransformerNUFFTNumPy branches (visibilities_from,image_from,transform_mapping_matrix) use finufft; nufftax loads only on JAX branches.__init__no longer imports nufftax.Interferometer.psf_precision_operator_from/apply_sparse_operatorandnufft_precision_operator_from(method="nufft"):use_jaxselects finufft vs nufftax. The dirty image inapply_sparse_operatoralways uses the NumPy path.pyproject.toml: finufft in base dependencies anddev.Decisions taken (please review)
nufft2d1) runs on one thread so the dirty image and precision operator are bitwise reproducible: a multithreaded type-1 spread sums thread subgrids in a non-deterministic order (13 bitwise-equality tests failed with OMP threads > 1; first CI run red on py3.13). Cost: ~0.9 s instead of ~0.3 s once per job on 5.5M visibilities (still ~10x faster than nufftax). The likelihood never calls type-1; type-2 (visibilities_from, deterministic) keeps finufft's threads.nufft_cpurecords the first process that ran finufft and passesnthreads=1in processes forked from it. Users pinningOMP_NUM_THREADS=1are unaffected.pip install autoarraynever tries to build finufft from source._sparse_parity_setuptest now usesmethod="numpy": its curvature matrix (cond ~4e9) amplifies the on-spec 4e-13 NUFFT error past the test's 1e-4 tolerance; on realistic data both NUFFTs match the brute force to ~2e-14.Migration
use_jax=Trueto the operator builder keep nufftax; dropping it gives the faster finufft build.Generated by the PyAutoLabs agent workflow.
🤖 Generated with Claude Code
https://claude.ai/code/session_013C7Zd6ibK9J4V8CFEUzrJU