Skip to content

Price CP2 recompute per rank on each layer type's layout - #978

Draft
bradhilton wants to merge 37 commits into
dalinar/recompute-mixer-floorfrom
dalinar/cp-layout-recompute-floor
Draft

bradhilton wants to merge 37 commits into
dalinar/recompute-mixer-floorfrom
dalinar/cp-layout-recompute-floor

Conversation

@bradhilton

@bradhilton bradhilton commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

With #1002 (merged in through #963), each CP rank also prices #1002's adapter-gradient term on its own layouts:

  • Per-rank boundaries. Each rank walks its own saved boundaries, one gradient group after another.
  • Paired floors. The extra is paired with that rank's own floor.
  • Why paired. A single short CP2 sequence can leave one rank with no GDN rows. That rank's extra is then almost every adapter gradient, and adding it to the other rank's floor over-counted by up to 632 MB.
  • Result. On the full stack (Qwen3.6-35B-A3B, 40 layers, CP2, one real sequence per wave), cold first waves come out +0.9% to +2.0% raw at EP1 and +3.0% to +13.4% at EP2. None are under.

Follow-up to #963 (stacked on it). At CP2, TrainerRank's checkpoint floor now prices each context-parallel rank on its own layouts, instead of pricing every rank on the busiest rank's rows with one mixer width. This makes the estimate correct per rank rather than tighter: on the measured workloads its accuracy is about unchanged.

Why: the two CP2 ranks don't hold the same work.

  • On a real-data batch, rank 0 held 52,480 attention rows and rank 1 44,314. Rank 1's attention still kept more memory for backward (5.76 GB vs 4.15 GB), because its remote stage covers all its queries, so it runs two full-length stages.
  • The old floor charged both ranks 5.00 GB for attention. That was 0.76 GB under for rank 1, hidden by over-charges on boundaries and GDN.

What changes (CP2, TP1, ART's CP core attention without a softmax offset, gradient groups; everything else keeps the old floor):

  • Saved boundaries use the layout each layer's input arrives in. GDN layers that follow another GDN layer take GDN-layout rows; every other layer takes attention-layout rows.
  • A recomputed attention layer is priced on attention rows, plus what the CP executor keeps for backward. That comes from a size-only mirror of the executor (retained_stage_record_bytes), kept next to the executor code.
  • A recomputed GDN layer is priced on GDN rows.
  • The MoE stage uses each layer's own rows for its local terms. Routed rows are the EP share when the EP group is the CP group, and otherwise the busiest rank's rows, as before. The MoE workspace no longer clamps routed rows to a rank's local rows, since a rank can receive more than it holds.
  • Plan pricing and admission take the largest rank. Building the peer rank's CP plan costs about 40–76 ms the first time a batch layout is planned (under 1 ms once cached), now counted in planning time. (Under CP, width search already admits on materialized plans.) The split search's lower bound prices even-share layouts at the least attention state, so it stays below the per-rank cost.

Measured against the PyTorch peak on the most-loaded rank, EP2/CP2 on two H200s. Peaks and losses are identical before and after; only the estimate changes. A later fix counts one more LSE buffer per attention stage, which adds under 0.01 GB, inside this table's rounding.

case before (cold / warm) after (cold / warm)
real data, 40 layers +18.2% / +19.2% +18.2% / +20.2%
random weights, 8 layers +26.5% / +23.6% +26.6% / +23.7%
random weights, 40 layers +19.7% / +17.5% +18.8% / +16.6%

The real-data warm call rises because its rank 1 again runs two full-query stages, which the old floor under-priced.

Limitation. The executor mirror and the layout ledger are validated at CP2 against allocator traces of Qwen3.6-35B-A3B, within 0.3%. No test yet runs the executor itself against the mirror; that needs GPUs. CP4 and other executor configurations keep the old floor. GDN keeps its existing per-row width, now on GDN rows. The EP routing allowance, which accounts for most of the remaining EP2 gap, is unchanged.

Planner-miss reports replay the per-rank pricing on CPU. Each group's CP layouts and the decoder's per-layer input layouts are recorded with the selected plan.

Testing: trainer-rank, CP and planner-replay unit tests pass on CPU; the table's runs are on local H200s.

🤖 Generated with Claude Code

bradhilton and others added 5 commits September 25, 2026 22:28
A size-only mirror of the executor's record_for_backward path, beside the
code it mirrors: per stage, the Q/K/V flex consumes (padded copies, else
contiguous copies of permuted views, or kept gathers and fetch buffers),
flex's output and LSE at the execution length, logical copies when padded,
and a merge-tape clone for every producing stage after the first. It
reproduces the traced CP2 ranks: 0.971 GB for an aligned single stage and
3.07 GB for a padded local plus full-query remote stage.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The checkpoint floor priced every rank on the busiest rank's rows with one
mixer width, which over-counted boundaries and GDN and under-counted a rank
whose attention runs two full-query stages. At CP2/TP1 with ART's CP core
attention, price each rank on its own layouts instead: saved boundaries by
each layer input's layout, a recomputed attention layer on attention rows
plus what the executor keeps for backward, a GDN layer on GDN rows, and the
MoE stage on that layer's rows with routed rows on the EP share. Admission
takes the largest rank. Elsewhere the busiest-rank floor is unchanged.

A rank can receive more routed rows than it holds, so routed rows are no
longer clamped to local rows.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The split search's lower bound priced gated plans with the busiest-rank
attention width, above what per-rank pricing can charge; price even-share
layouts at the least attention state instead (one aligned local stage per
rank). Count flex's saved LSE beside the normalized copy it returns.
Share one gate between plan pricing and the bound, checking the topology
before model state. Record group layouts in planner evidence.

Tests cover the positive gate path against the executor's own plans, the
runtime layouts, the softmax-offset gate, tiny and single-head stages, and
the lower bound staying below plan cost.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The gate now declines models with several chunks or a decoder without
layers before reading them. The bound holds because every rank's total
grows with its own rows, so the largest is at least the total at the mean;
rounding the even share up can exceed a split's exact cost. The lower-bound
test covers even, skewed and odd splits and one long sequence.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@bradhilton
bradhilton deployed to trainer-rank-gpu-validation September 25, 2026 23:53 — with GitHub Actions Active
…planning

One head does not make a view of a fused QKV split contiguous, so the
mirror now charges the copy flex makes of any full local view; the lower
bound still counts only multi-head copies. A partial-query merge tape also
keeps its int64 row index. The per-rank layout work now counts toward
planning time (about 40-76 ms for a new layout's peer plan, under 1 ms once
cached). Tests use typed geometry helpers.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@bradhilton
bradhilton had a problem deploying to trainer-rank-gpu-validation September 26, 2026 00:24 — with GitHub Actions Error
The executor keeps a partial stage's int64 row index even when that stage
produced first and recorded no accumulator tape, so charge indices apart
from the tape the mirror drops.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@bradhilton
bradhilton deployed to trainer-rank-gpu-validation September 26, 2026 00:31 — with GitHub Actions Active
@bradhilton
bradhilton marked this pull request as ready for review September 26, 2026 15:46
@bradhilton
bradhilton had a problem deploying to trainer-rank-gpu-validation September 26, 2026 15:46 — with GitHub Actions Failure
@bradhilton
bradhilton marked this pull request as draft September 26, 2026 16:08
Picks up main (0e0c31b) through the updated #963 branch. The layout floor
sits between #988's TP > 1 floor and the generic floor, and #971's combine-
extent floor applies after all three. Tests pass routed rows and layouts by
keyword.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bradhilton added a commit that referenced this pull request Sep 26, 2026
Picks up main (0e0c31b) through the updated #963 and #978 branches.
_checkpoint_floor_decoder stays TP1 by default, so the dense widths and
their discounts remain TP1/CP2 only; with sequence_parallel it applies main's
#988 checks for the traced TP x SP floor. _checkpoint_memory_floor prices
TP > 1 with #988's floor, then the layout and generic floors, and #971's
combine-extent floor after all three.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bradhilton added a commit that referenced this pull request Sep 26, 2026
Picks up main (0e0c31b) through the updated #963 and #978 branches. Clean
merge; the source equals the composition measured in M9 plus #998.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@bradhilton
bradhilton had a problem deploying to trainer-rank-gpu-validation September 26, 2026 23:14 — with GitHub Actions Failure
bradhilton and others added 2 commits September 26, 2026 23:27
…outs

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@bradhilton
bradhilton had a problem deploying to trainer-rank-gpu-validation September 27, 2026 00:32 — with GitHub Actions Failure
bradhilton and others added 3 commits September 28, 2026 06:48
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bradhilton added a commit that referenced this pull request Sep 28, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bradhilton added a commit that referenced this pull request Sep 28, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bradhilton added a commit that referenced this pull request Sep 28, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bradhilton and others added 15 commits September 28, 2026 13:24
Per-rank CP layouts: the head stage takes the largest rank's adapter term
over its own boundaries, sharing the per-rank walk with the decoder stage's
extra.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…acted layout

Port #978 (through 6dc567b) onto the extracted planner modules: every
CP2 rank's checkpoint boundaries and recomputed layer are priced on its
own attention and GDN layouts plus the CP executor's retained stage
records, with adapter gradients paired per rank. Grouped planner-miss
replay freezes each group's layouts and the decoder's per-layer input
layouts (facts version 4).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Validate an empty GDN layout's length, require the TP1/CP2/PP1 topology
that layout pricing is limited to, and refuse a recorded group_layouts
argument in any estimate.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@bradhilton
bradhilton had a problem deploying to trainer-rank-gpu-validation September 29, 2026 07:11 — with GitHub Actions Error
@bradhilton
bradhilton deployed to trainer-rank-gpu-validation September 29, 2026 07:43 — with GitHub Actions Active
bradhilton added a commit that referenced this pull request Sep 29, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bradhilton added a commit that referenced this pull request Sep 29, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bradhilton added a commit that referenced this pull request Sep 29, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bradhilton added a commit that referenced this pull request Sep 29, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bradhilton added a commit that referenced this pull request Sep 29, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bradhilton added a commit that referenced this pull request Sep 29, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bradhilton added a commit that referenced this pull request Sep 29, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bradhilton added a commit that referenced this pull request Sep 29, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bradhilton added a commit that referenced this pull request Sep 29, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bradhilton added a commit that referenced this pull request Sep 29, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
trainer-rank-gpu-validation — bf79e446 Deployed Sep 29, 2026 by bradhilton via Run on 2x H200 #976
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant