Skip to content

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

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

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

Conversation

@bradhilton

@bradhilton bradhilton commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

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.

Testing: trainer-rank and CP unit tests pass; 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

This branch had an error being deployed

1 failed deployment
trainer-rank-gpu-validation — 4368998e Deployed Sep 26, 2026 by bradhilton via Run on 2x H200 #764
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