perf: cross-eval memo for MGE operated mapping matrices (numba CPU inversion) - #455
Merged
Merged
Conversation
…version) A sampler builds fresh linear-func objects every likelihood evaluation, so with FIXED lens-light MGE parameters the identical ~60-Gaussian PSF convolution stack (~0.5 s of a ~2.4 s euclid numba CPU eval) is recomputed each call. InversionImagingSparseNumba now overrides linear_func_operated_mapping_matrix_dict with (1) per-inversion cached_property and (2) a module-level memo keyed by a sha256 of the linear func's full pickled state (profiles + grids + PSF): - fixed profiles fingerprint identically -> matrix reused across evals; - any free profile parameter changes the key -> recompute exactly as before (memo engages only when the MGE is actually fixed); - unpicklable objects fall back to the uncached parent computation; - failure modes are misses, never stale hits; entries are read-only copies, bounded at 8; AUTOARRAY_NUMBA_OPERATED_MEMO=0 disables. Scoped to imaging_numba/sparse.py only — no other inversion path, no public API, and no autogalaxy change (the batched-convolution half of the Mind prompt stays deferred). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vcc7MUBMnNU6n8qqS9ioVZ
Collaborator
Author
|
Adversarial parameterization check (user-requested): the memo distinguishes model parameterizations correctly and never returns a stale result when the MGE changes. Setup: the real euclid Delaunay-1250 fiducial, 12 interleaved likelihood evaluations over 6 parameter vectors (base; mass/shear-only jitters ×2; MGE-only jitters ×2; combined), run twice — memo on vs
CI is green on all three legs. Generated by Claude Code |
This was referenced Aug 21, 2026
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.
Closes #454.
What
With fixed lens-light MGE parameters, every likelihood evaluation rebuilds the identical ~60-Gaussian PSF-convolved operated mapping matrix (~0.56 s of a ~2.4 s euclid numba CPU eval), because samplers construct fresh linear-func objects per call — the func object's own
cached_propertynever survives an evaluation. Scope constraints (user-set): stay inside the numba inversion bit, minimal source interference, active only when the MGE is actually fixed.One file of source change (
autoarray/inversion/inversion/imaging_numba/sparse.py):InversionImagingSparseNumbaoverrideslinear_func_operated_mapping_matrix_dictwithcached_property(the dict is read by several matrix builds), andFixed profiles fingerprint identically → the matrix is reused across evaluations. Any free profile parameter changes the key → recompute exactly as before, so the memo self-gates on "MGE actually fixed" with no config or API surface. Unpicklable objects fall back to the uncached parent computation. Failure modes are misses, never stale hits (a fingerprint taken after cached-property pollution just misses consistently). Memo entries are read-only copies (every consumer copies or derives, never mutates), bounded at 8 entries;
AUTOARRAY_NUMBA_OPERATED_MEMO=0disables.The batched-convolution half of the originating PyAutoMind prompt (PyAutoGalaxy
linear/abstract.py) is deferred: outside the numba bit, and largely mooted for fixed-MGE campaigns since the convolution stack now runs once per worker.Results (4-core cloud container, Delaunay Hilbert-1250 campaign fiducial)
delaunay_numbapinned log-likelihoods pass at rtol 1e-6 (memo values are bitwise-identical reuses).Testing
test_autoarray/inversion/inversion/test_sparse_numba_operated_memo.py(8 tests): hit on identical state across fresh objects, recompute on changed state, unpicklable fallback, env-var disable, eviction bound, read-only buffers, per-inversion dict caching.test_autoarray/: 1034 passed, 51 skipped; only the 3 pynufft transformer tests that fail identically on stockmainin this environment (pre-existing).Downstream
No public API change; no other inversion path touched; JAX path untouched. Free-MGE models pay only the fingerprint cost (pickle + sha256, ~few ms against multi-second evals).
🤖 Generated with Claude Code
https://claude.ai/code/session_01Vcc7MUBMnNU6n8qqS9ioVZ
Generated by Claude Code