Skip to content

perf: cross-eval memo for MGE operated mapping matrices (numba CPU inversion) - #455

Merged
Jammy2211 merged 1 commit into
mainfrom
feature/numba-mge-operated-matrix-memo
Aug 21, 2026
Merged

perf: cross-eval memo for MGE operated mapping matrices (numba CPU inversion)#455
Jammy2211 merged 1 commit into
mainfrom
feature/numba-mge-operated-matrix-memo

Conversation

@Jammy2211

Copy link
Copy Markdown
Collaborator

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_property never 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): InversionImagingSparseNumba overrides linear_func_operated_mapping_matrix_dict with

  1. a per-inversion cached_property (the dict is read by several matrix builds), and
  2. a module-level cross-evaluation memo keyed by sha256 of the linear func's full pickled state (profiles + grids + PSF).

Fixed 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=0 disables.

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)

  • Euclid "MGE operated mapping matrix" step: 0.56 s → 0.004 s on memo hits.
  • Euclid steady-state eval: 2.34 s → 1.34 s; stacked on the fnnls solver speed-up (perf: in-place Cholesky buffer + copy-free numba solves for fnnls_cholesky #453), today's total is 4.92 s → 1.34 s (3.7×).
  • Both autolens_profiling delaunay_numba pinned log-likelihoods pass at rtol 1e-6 (memo values are bitwise-identical reuses).

Testing

  • New 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 stock main in 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

…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

Copy link
Copy Markdown
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 AUTOARRAY_NUMBA_OPERATED_MEMO=0 as ground truth in a separate process.

  • Gating: memo entry count over the sequence = [1,1,1,2,2,2,2,3,3,3,3,3] — mass/shear-only changes never miss (MGE fingerprint unchanged; reuse is legitimate since lens light is image-plane), each distinct MGE state creates exactly one new entry. The combined-jitter case correctly hit an earlier MGE-only entry whose bulge parameters it happened to share — keying tracks MGE content exactly, not evaluation order or the rest of the model.
  • Correctness: all 12 memo-on likelihoods match the memo-off twins to ≤4.5e-10 relative (pure-hit cases to 1e-12); interleaved revisits of the same vector are bitwise-identical within a run. The residual ~1e-10 process-to-process differences appear equally on the first (memo-cold) evaluation and match the solver's documented bistability — pre-existing nondeterminism, four orders of magnitude under the rtol 1e-6 pins.

CI is green on all three legs.


Generated by Claude Code

@Jammy2211
Jammy2211 merged commit 1c33850 into main Aug 21, 2026
3 checks passed
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.

perf: cross-eval memo for MGE operated mapping matrices (numba CPU inversion, fixed-MGE campaigns)

2 participants