Memoize live results in RAM to avoid duplicate computation#17
Open
vincenzoml wants to merge 3 commits into
Open
Memoize live results in RAM to avoid duplicate computation#17vincenzoml wants to merge 3 commits into
vincenzoml wants to merge 3 commits into
Conversation
MaterializationStore.put() replaced image-like values (image/bytes/ ndarray/overlay) with a node-id placeholder in the in-memory record, and get() then had to round-trip to the backend to recover them. With no backend (--no-cache) that round-trip returned None, so a node shared by multiple consumers was recomputed once per consumer -- a diamond DAG over images recomputed the shared subtree every time it was demanded. Keep the real value in the in-memory record for all types and return it directly from get(). Each node is now computed at most once per run regardless of the backend; with a backend, reuse no longer re-reads and re-deserializes the payload from disk on every demand. This trades memory for compute (live intermediates are now held for the run); the follow-up two-level cache bounds that memory with an LRU tier. Co-Authored-By: Claude Opus 4.8 <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.
Tracking issue: #14 — fixes defects §2/§3.1 (no in-RAM image memo → recompute under
--no-cache) and §3.2 (repeated disk deserialize under--store-db). Does not address §3.3 (double serialize/write) or §4 (node-level parallelism), which stay open in #14.Summary
First of two stacked PRs addressing the lazy-interpreter caching defects in #14. This one is the minimal correctness fix; the follow-up (#TBD) layers a bounded two-level cache on top.
Scope: avoid duplicate computation only. No parallelization.
The defect
MaterializationStore.put()replaced image-like values (image/bytes/ndarray/overlay) with a node-id placeholder in the in-memory record:get()then had to round-trip to the backend to recover the value. With no backend (--no-cache) that round-trip returnsNone, so_evaluate_node_lazy's top-levelcache_lookupmisses and the node is recomputed on every demand. A node shared by N consumers (a diamond DAG over images — exactly the BraTS sweeps) recomputes its whole subtree N times. Scalars were unaffected because their real value was kept.The fix
Keep the real value in the in-memory record for all types; return it directly from
get(). Each node is now computed at most once per run regardless of backend. With a backend present, reuse also stops re-reading and re-deserializing the payload from disk on every demand.Two small edits in
storage.py(put,get), plus removal of the now-dead placeholder branch.Trade-off
Live intermediates are now held in RAM for the duration of the run (previously image-like values were dropped). The stacked follow-up PR bounds this with an LRU memory tier backed by the disk tier — the "two-level cache" of #14.
Tests
tests/unit/test_inrun_memo.py: an ndarray result is returned fromget()with no backend (the exact case that used to recompute), plus a scalar round-trip.test_async_persistenceand the storage/execution unit tests still pass.--no-cacheverified.(Pre-existing unrelated failures in
test_default_primitives.py—SequenceValue/.compute()API drift — fail identically onmain.)Refs #14
🤖 Generated with Claude Code