Skip to content

fix: stride the pad-token replay fill across experts - #2697

Open
EazyReal wants to merge 1 commit into
radixark:mainfrom
EazyReal:upstream-pr/stride-pad-replay-fill
Open

fix: stride the pad-token replay fill across experts#2697
EazyReal wants to merge 1 commit into
radixark:mainfrom
EazyReal:upstream-pr/stride-pad-replay-fill

Conversation

@EazyReal

@EazyReal EazyReal commented Aug 21, 2026

Copy link
Copy Markdown

Summary

Routing replay reuses stored top-k selections during training. When replay data is padded to the training token layout, fully padded rows are represented as all -1; those sentinels must be replaced with in-range indices before downstream gather and dispatch.

The existing repair writes the same arange(topk) % n_cols row into every fully padded row. For MoE routing, n_cols is the number of experts, so every pad token goes to experts 0..topk-1. Loss masking prevents those rows from affecting the objective, but it does not skip the forward expert dispatch: with topk <= experts-per-rank, rank 0 receives topk x pad_count synthetic assignments (and larger top-k values concentrate them on the first EP ranks).

This surfaced as a trainer OOM on a 128x H100 DeepSeek-V4-Flash run at 262,144-token context. Modeling the constant fill predicted a hot-rank receive count of 719,029 tokens versus 718,848 observed at the OOM site (0.025% error).

Fix

Number only the fully invalid rows and fill them by pad-row ordinal:

fill[pad_row, col] = (pad_row * topk + col) % n_cols

This makes the synthetic assignments independent of where padding appears in the batch. That distinction matters for BSHD batches, where per-sample padding can recur at regular token positions and an absolute token-position stride can alias back to the same expert block. The arange is also sized to the invalid rows rather than the full [n_tokens, topk] tensor, and the replay tensor is cloned before assignment.

Fully padded rows are loss-masked, so any in-range selection is semantically valid. Selections remain distinct within each row whenever topk <= n_cols. Partially invalid rows remain unchanged for the indexer path, where -1 has separate meaning; for fully padded indexer rows, n_cols denotes KV positions and the same fill remains in range.

Verification

  • The regression test uses noncontiguous pad rows at the same per-sample position. It fails both the constant fill and an absolute token-position stride, and pins the pad-row-ordinal result.
  • The existing partial-padding test verifies that rows containing valid indexer selections are not rewritten.
  • python -m pytest -q tests/fast/utils/test_replay_base.py tests/fast/backends/test_fsdp_replay_routers.py: 13 passed on CPU-only torch.
  • ruff, isort, and black pass on both changed files.

Routing replay fills fully padded rows with the constant row
arange(topk) % n_cols, routing every pad token to columns 0..topk-1 —
which for MoE expert routing under expert parallelism all live on the
first EP rank(s), landing topk x pad-count extra tokens there. Stride by
pad-row ordinal instead so pad load cycles across the columns regardless
of where padding occurs, while allocating the fill only for repaired rows.
Pads are loss-masked, so any in-range index is valid; this also holds for
the indexer replay path, where columns are KV positions.

Measured on a 128x H100 DeepSeek-V4-Flash run at 262,144-token context:
modeling the constant fill predicted a hot-rank receive count of 719,029
tokens vs 718,848 observed (0.025% off) at a real trainer OOM site.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@EazyReal
EazyReal marked this pull request as ready for review August 22, 2026 21:36

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

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