pack: use NVMe as a cache tier so the model need not live there - #61
Merged
Merged
Conversation
Measured yesterday: a qwen4exp reference paging its working set off /mnt/deepmem ran at 63 s/token. That volume is a 4-device btrfs over four SPINNING disks shared with a household stack, and the obvious fix — copy the model to NVMe — does not generalise: a 207 GB pack and a 111 GB model do not both fit the fast disk, and copying is a manual step that has to be repeated. So leave the pack where it lives and cache the ranges actually read. `mummu::diskcache::DiskCache` sits in front of `Pack::read_range`, which is the single choke point every blob byte already passes through. Keyed on the EXACT requested range, not on blocks. A general cache has to guess a block size; this one does not, because a pack is read at `(precision, offset, len)` triples that are identical every token — the same tensor, the same slice. So a lookup is an exact hit or an exact miss, with no partial-block reassembly and no amplification from a block size that fits nothing. Eviction is coldest-first on DECAYING HOTNESS with an LRU tiebreak, not plain LRU. MoE routing is skewed and plain LRU discards a persistently hot expert after one cold burst — llama.cpp PR #25294 reports the same and evicts the same way. The test for this is the MoE case directly: one entry routed repeatedly, others touched once, and the hot one must survive an insert that forces eviction even though it is no longer the most recent. Failure behaviour is "degrade to a miss", never "fail the load": a cache file that vanished (something cleaning /var/tmp) or is short reads as a miss and drops its own bookkeeping; an entry larger than the whole cache is declined rather than evicting everything to not fit; writes go to a temp name and are renamed, so a crash cannot leave a short file that a later read trusts by size. A pack read returns identical bytes whether they came from the blob or the cache — placement affects speed, never contents, and there is a test asserting exactly that against a real `read_range`. Opt-in via MUMMU_DISK_CACHE_DIR (+ MUMMU_DISK_CACHE_GB, default 64). Never implicit: this writes tens of GB to whatever filesystem it is pointed at, which is not something to start doing to someone's root volume because a model happened to load. Read-through only for now — it populates on miss and never prefetches. The access order IS known in advance, so preload is the natural next increment and is filed as its own roadmap item along with the two other things the research flagged (`O_DIRECT` once the model exceeds RAM; per-session ownership of the residency pool). Verified: cargo fmt clean; cargo clippy --workspace --all-targets clean; workspace lib tests green at 496 (+8 new). 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.
Measured yesterday: a qwen4exp reference paging its working set off
/mnt/deepmemran at 63 s/token. That volume is a 4-device btrfs over four spinning disks shared with a household stack.The obvious fix — copy the model to NVMe — doesn't generalise: a 207 GB pack and a 111 GB model don't both fit the fast disk, and copying is a manual step that has to be repeated. So: leave the pack where it lives and cache the ranges actually read.
mummu::diskcache::DiskCachesits in front ofPack::read_range, the single choke point every blob byte already passes through.Keyed on the exact range, not on blocks
A general cache has to guess a block size. This one doesn't: a pack is read at
(precision, offset, len)triples that are identical every token — same tensor, same slice. So a lookup is an exact hit or an exact miss, with no partial-block reassembly and no read amplification from a block size that fits nothing.Eviction is hotness-based, not LRU
Coldest-first on decaying hotness with an LRU tiebreak. MoE routing is skewed and plain LRU discards a persistently hot expert after one cold burst — llama.cpp #25294 reports the same and evicts the same way.
The test is the MoE case directly: one entry routed repeatedly, others touched once, and the hot one must survive an insert that forces eviction even though it is no longer the most recent.
Failure behaviour is "degrade to a miss", never "fail the load"
/var/tmp) or is short reads as a miss and drops its own bookkeepingread_rangeOpt-in, deliberately
MUMMU_DISK_CACHE_DIR(+MUMMU_DISK_CACHE_GB, default 64). Never implicit: this writes tens of GB to whatever filesystem it's pointed at, which isn't something to start doing to someone's root volume because a model happened to load.Scope
Read-through only — it populates on miss and never prefetches. The access order is known in advance (manifest order;
workingsetalready exploits exactly that for RAM→VRAM), so preload is the natural next increment and is filed as its own roadmap item, along with the two other things the research flagged:O_DIRECTonce the model exceeds RAM, and per-session ownership of the residency pool.Verification
cargo fmt --checkclean;cargo clippy --workspace --all-targetsclean🤖 Generated with Claude Code