Overview
The fnnls warm-start memo (on by default since #498) seeds each positive-only solve from the previous evaluation's final passive set. On a scattered evaluation stream (iid draws, e.g. Nautilus early live points) the seed is bad, the post-solve fallback guard drops it, the next solve restarts dense and re-seeds -- so every other solve pays for a bad seed. autolens_profiling#332 measured the alma interferometer Delaunay solve 2.17x slower memo-on vs memo-off on an iid stream (rect 1.08x), while a local walk gains 0.68x / 0.13x. This adds a per-key back-off so the memo stops re-seeding a key that keeps falling back, and re-probes it on an exponential schedule so a stream that turns local recovers the gain.
Source task: organs/PyAutoPulse/tasks/interferometer_nnls_memo_scattered_stream_guard.md (related autolens_profiling#332).
Plan
- Reproduce locally with a small CPU witness (scattered vs local-walk stream, solver-only timing) before changing anything.
- Track, per memo key, how many seeded solves in a row fell back.
- After 2 consecutive fallbacks, skip the memo seed (solve dense, still refreshing the entry) for an exponentially growing number of solves (1, 2, 4, ... capped at 32), then probe the seed again; an accepted seed resets the streak.
- A local-walk stream never reaches two consecutive fallbacks, so its behaviour (and every reconstruction) is unchanged; no default tolerance or config key changes.
- Unit tests for both streams over several seeds; re-time the witness.
Tier: glance — merge mode: human /prm (scope of this session ends at a local commit; Heart RED, shipping is the human's call)
Detailed implementation plan
Affected Repositories
Branch Survey
| Repository |
Current Branch |
Dirty? |
| ./PyAutoArray |
main |
clean |
Suggested branch: feature/nnls-memo-scattered-backoff
Worktree root: ~/Code/PyAutoLabs-wt/nnls-memo-scattered-backoff/
Implementation Steps
autoarray/inversion/inversion/nnls_memo.py: add a bounded per-key back-off table (fallback streak, skip remaining), with backoff_should_skip(key), backoff_record_fallback(key), backoff_record_accept(key); constants _NNLS_BACKOFF_AFTER_FALLBACKS = 2, _NNLS_BACKOFF_MAX_SKIP = 32.
autoarray/inversion/inversion/inversion_util.py::reconstruction_positive_only_from: consult the back-off before reading the memo entry; record fallback / accept after the existing ratio guard; dense solves still refresh the entry.
test_autoarray/inversion/inversion/test_nnls_memo.py: state-machine tests; iid stream (several seeds) — seeded solves bounded, reconstructions equal memo-off to round-off; local walk (several seeds) — back-off never engages and reconstructions are bit-identical with the back-off disabled.
Key Files
autoarray/inversion/inversion/nnls_memo.py
autoarray/inversion/inversion/inversion_util.py
test_autoarray/inversion/inversion/test_nnls_memo.py
Original Prompt
Click to expand
See the Pulse task file above; Witness: on a recorded real-sampler evaluation sequence the memo-on fnnls solve is no slower than memo-off on every phase, keeping >= 80 % of the local-walk gain; figure of merit unchanged.
Overview
The fnnls warm-start memo (on by default since #498) seeds each positive-only solve from the previous evaluation's final passive set. On a scattered evaluation stream (iid draws, e.g. Nautilus early live points) the seed is bad, the post-solve fallback guard drops it, the next solve restarts dense and re-seeds -- so every other solve pays for a bad seed. autolens_profiling#332 measured the alma interferometer Delaunay solve 2.17x slower memo-on vs memo-off on an iid stream (rect 1.08x), while a local walk gains 0.68x / 0.13x. This adds a per-key back-off so the memo stops re-seeding a key that keeps falling back, and re-probes it on an exponential schedule so a stream that turns local recovers the gain.
Source task:
organs/PyAutoPulse/tasks/interferometer_nnls_memo_scattered_stream_guard.md(related autolens_profiling#332).Plan
Tier: glance — merge mode: human /prm (scope of this session ends at a local commit; Heart RED, shipping is the human's call)
Detailed implementation plan
Affected Repositories
Branch Survey
Suggested branch:
feature/nnls-memo-scattered-backoffWorktree root:
~/Code/PyAutoLabs-wt/nnls-memo-scattered-backoff/Implementation Steps
autoarray/inversion/inversion/nnls_memo.py: add a bounded per-key back-off table (fallback streak,skip remaining), withbackoff_should_skip(key),backoff_record_fallback(key),backoff_record_accept(key); constants_NNLS_BACKOFF_AFTER_FALLBACKS = 2,_NNLS_BACKOFF_MAX_SKIP = 32.autoarray/inversion/inversion/inversion_util.py::reconstruction_positive_only_from: consult the back-off before reading the memo entry; record fallback / accept after the existing ratio guard; dense solves still refresh the entry.test_autoarray/inversion/inversion/test_nnls_memo.py: state-machine tests; iid stream (several seeds) — seeded solves bounded, reconstructions equal memo-off to round-off; local walk (several seeds) — back-off never engages and reconstructions are bit-identical with the back-off disabled.Key Files
autoarray/inversion/inversion/nnls_memo.pyautoarray/inversion/inversion/inversion_util.pytest_autoarray/inversion/inversion/test_nnls_memo.pyOriginal Prompt
Click to expand
See the Pulse task file above; Witness: on a recorded real-sampler evaluation sequence the memo-on fnnls solve is no slower than memo-off on every phase, keeping >= 80 % of the local-walk gain; figure of merit unchanged.