Price warm waves by the fit later plans measured, not the first plan's - #991
Merged
Merged
Conversation
bradhilton
deployed
to
trainer-rank-gpu-validation
September 26, 2026 16:59 — with
GitHub Actions
Active
bradhilton
had a problem deploying
to
trainer-rank-gpu-validation
September 26, 2026 17:58 — with
GitHub Actions
Failure
bradhilton
deployed
to
trainer-rank-gpu-validation
September 26, 2026 18:39 — with
GitHub Actions
Active
A signature's memory profile max-merged every observed peak rate, so the first executed plan's one-time costs (compilation, first-use workspaces) priced every later wave. A small, cold first wave spreads those costs over few tokens. On real Qwen3.6-35B-A3B (40 layers, CP2/EP2), the run's first wave (15.6k tokens) peaked at 275 KB per packed token and later waves ran 206-247 KB; that profile bound 16 of 17 waves per run. The profile now also keeps a warm fit over every plan after the first: the max rate, the smallest size and the max sharing ratio. The first plan is held by weak reference, so its caller-phase update stays provisional and a later plan at its freed address is still warm. Waves at least as large as the smallest later plan are priced at the lower of the warm fit and today's fit; a rate learned under lighter sharing scales up for deeper-shared waves as today's does. Smaller waves, and profiles without warm fields (replayed reports), price as before. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Review found two problems with the warm fit. The size gate made cost drop at the smallest warm plan's size. The width search accepts a width on the cheap no-sharing count and rejects on the full-sharing count, so a shared layout below that size could execute priced above the estimate that admitted it, and the lower bounds could refuse feasible widths. A smaller wave is now priced by the warm fit as if it were the smallest warm plan, and admission takes the lower of that and today's fit. Cost is monotone in tokens again. This is sound where memory is a fixed cost plus a per-token rate, since that plan's rate covers its share of the fixed cost. Split children and dp_rank_forward observe forward only, so they could set a warm rate without the backward peak. Only a flat wave's caller-phase peak now feeds the warm fit, and the profile's first such plan is the seed, counted in the profile rather than held by weak reference. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A nested tracked forward during a wave's yield resets the CUDA peak counter, so the caller-phase reading then misses the wave's own forward and backward. On main that reading was only max-merged; with the warm fit it could set the warm rate. The micro-batch loop now captures the wave's interval (tracked resets, forward peak) before yielding, and the caller phase fits the warm profile only if no tracked forward reset the counter since and the counter has not fallen below the wave's forward peak. Other readings (forward-only, split children, interrupted caller phases) cannot create or extend the warm fit, but a higher one now raises its rate, as it raises the fit over every observation. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A reading that cannot fit the warm profile (forward-only, a split child, an interrupted caller phase) only raised an existing warm rate, so one taken between the seed and the first whole warm plan was dropped when that plan created the fit. After the seed, every reading now raises a pending warm rate, which stays inert for pricing until a whole warm plan fits the size extent and sharing. The forward_micro_batches docstrings state which waves can lower later estimates. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bradhilton
force-pushed
the
dalinar/profile-cold-seed
branch
from
September 26, 2026 19:47
4753dd4 to
8ae2585
Compare
bradhilton
had a problem deploying
to
trainer-rank-gpu-validation
September 26, 2026 19:48 — with
GitHub Actions
Error
Backward is learned only when it runs inside the yield; a deferred backward is not detected. Only a nested TrainerRank forward is enforced. Also let the cache-recovery test's profile stub accept the new keywords. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bradhilton
deployed
to
trainer-rank-gpu-validation
September 26, 2026 19:58 — with
GitHub Actions
Active
bradhilton
marked this pull request as ready for review
September 26, 2026 20:18
bradhilton
deployed
to
trainer-rank-gpu-validation
September 26, 2026 20:19 — with
GitHub Actions
Active
bradhilton
added a commit
that referenced
this pull request
Sep 26, 2026
…d admission method bodies Pure code motion following the _memory / _gdn_memory precedent: 34 method bodies moved verbatim from _impl as module-level functions taking the rank as self. Names the bodies read from _impl's namespace (torch, dist, time, _telemetry_phase, plan/cost types, sibling helpers) are resolved as _impl.X at call time so tests that patch them on _impl keep intercepting; stdlib helpers and the unpatched prefix-tree / planner-cost functions are imported directly. @contextmanager stays on _planning_status and @_backward_region on _recover_admission. _forward_micro_batches carries the #991 caller-phase interval body.
bradhilton
added a commit
that referenced
this pull request
Sep 27, 2026
…d admission method bodies Pure code motion following the _memory / _gdn_memory precedent: 34 method bodies moved verbatim from _impl as module-level functions taking the rank as self. Names the bodies read from _impl's namespace (torch, dist, time, _telemetry_phase, plan/cost types, sibling helpers) are resolved as _impl.X at call time so tests that patch them on _impl keep intercepting; stdlib helpers and the unpatched prefix-tree / planner-cost functions are imported directly. @contextmanager stays on _planning_status and @_backward_region on _recover_admission. _forward_micro_batches carries the #991 caller-phase interval body.
This branch was successfully deployed
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.
A signature's first wave pays one-time costs (compilation, first-use workspaces). TrainerRank's memory profile keeps the highest per-token rate it has seen, so a small, cold first wave overprices every later wave. On Qwen3.6-35B-A3B that first wave ran 275 KB/token; later waves ran 206–247 KB/token.
Change: the profile also learns a warm rate from later waves, and admission uses the lower of the two.
dp_rank_forward, interrupted waves) can raise the warm rate but never create it.Before/after (Qwen3.6-35B-A3B, 40 layers, CP2, 8 steps; "today" prices the same waves without the warm rate):
Testing: 15 new CPU tests, including integration tests through the real width search, split waves and a nested forward during a wave's caller phase, plus the GPU run above; the trainer-rank suite passes.
Limits:
🤖 Generated with Claude Code