Expand description
Residency analysis + eviction for the pipelined executor.
Ported from fuel-graph-router::{residency_planner, residency_eviction} (executor-unification Session 6, 2026-06-11).
The legacy shape was a GraphMutatingSchedulerRule that emitted a
three-node Op::Copy{Cpu} + Op::Release + Op::Copy{device}
chain for the legacy GraphExecutor<Router>; the pipelined port
emits the fused two-node form — Op::Move{Cpu} + reload
Op::Copy{device} — making this pass the first production emitter
of WorkItemKind::Move (shipped b93bdb82).
§The two halves
- Analysis —
ResidencyPlanner::analyzewalks a graph’s topo order, tracks each node’s live range (first use → last consumer), and computes the peak working-set size. Pure; no graph mutation. - Transform —
insert_residency_evictionsconsumes the analysis and, while the peak exceeds a byte budget, insertsOp::Move{Cpu}+ reloadOp::Copy{device}chains around the highest-scoring candidates (bytes × inactive_gap). Thederive_orderinghalf ofexecution_plan(run inside both pipelined realize paths) pins each Move after every non-destructive reader of its source, and the executor’sdestructive_inputcleanup frees the device storage when the Move runs.
§Const-pool byte budget (deferred — planner program)
The legacy executor’s with_const_pool_limit LRU was the only
other larger-than-VRAM mechanism, and it retired with the legacy
executor. Per the 2026-06-11 re-audit (gap 7), the replacement is
NOT an executor-side LRU: weight residency under a byte budget is
a planning decision, and it folds into the load-time incremental
planner’s residency program (docs/session-prompts/ load-time-incremental-planner.md) — the planner prices
evict/reload chains with Stage 1 TransferCalibration data and
emits the same Op::Move/Op::Copy primitives this module does.
This module is that program’s substrate, not its policy.
§Known limitations (follow-up work, inherited from the port)
- Only one eviction per candidate (the largest gap). Multiple gaps would need multiple evict chains.
- Greedy selection; no cost-awareness for the CPU↔device transfer overhead vs the VRAM savings (the planner program adds pricing).
- No integration with the
VulkanBackend::evictmmap-tiering path — that’s a transparent runtime mechanism, distinct from graph-level planning.
Structs§
- Evict
Reload - One evict/reload chain emitted by
insert_residency_evictions.move_nodeis theOp::Move { target: Cpu }(destructive stage- to-host);reloadis theOp::Copy { target: src_device }the post-gap consumers were rewired to. - Live
Range - One tensor’s residency span.
[first_use, last_use]are op positions in a topo order (inclusive — the tensor is live during both).bytesis the output storage size.inactive_gapis the longest stretch of ops between consecutive reads where the tensor is resident but not accessed — a strong signal for eviction viability. - Residency
Planner - Analysis-only residency planner. Computes live ranges and peak
bytes for a graph, emits a
ResidencyReport. Does not mutate the graph. Takes&Graph— the caller holds whatever lock it already has; no hidden lock acquisition. - Residency
Report - Structured report on a graph’s residency profile.
Functions§
- insert_
residency_ evictions - Graph-mutating eviction pass: while the graph’s peak residency
exceeds
budget_bytes, pick the top candidate (bybytes × inactive_gap) that has a realizable inactive gap and insert anOp::Move{Cpu}+ reloadOp::Copy{device}chain around it (viafuel_graph::opt::insert_evict_reload).