Skip to content

fix(trainer): distribute routing replay padding across experts - #3350

Closed
EazyReal wants to merge 1 commit into
PrimeIntellect-ai:mainfrom
EazyReal:fix/moe-routing-replay-padding
Closed

EazyReal wants to merge 1 commit into
PrimeIntellect-ai:mainfrom
EazyReal:fix/moe-routing-replay-padding

Conversation

@EazyReal

@EazyReal EazyReal commented Aug 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Sequence packing appends loss-masked tokens to align training batches. With router replay enabled, those tokens still pass through MoE dispatch, but their replay payload was filled with zero bytes. Every synthetic route therefore selected expert 0, concentrating padding-only forward work on one expert and potentially one expert-parallel rank.

Fix

  • Read the model's routed-expert count from the same configuration already loaded by the batch packer, including composite text configs.
  • Distribute each layer's complete padding route set as full expert cycles plus an evenly spaced remainder, then rotate assignments between layers. The cycle order keeps every row's top-k distinct across cycle boundaries, bounds per-expert count skew to one assignment, and spreads the unavoidable remainder optimally across any contiguous expert-parallel partition.
  • Widen compact replay payloads when the model's expert range requires it, preserving all sampled route values. For example, a uint8 payload for a 512-expert model becomes uint16 before padding is appended.
  • Fail closed before mutating the batch when routing padding is required but the expert count is unavailable.

Non-padding replay routes and loss-mask behavior are unchanged.

Verification

Validated at 893604c3f10d6153eb261dd7e51e98cbf38f8146, based on main 91f58bd9d958860a8414284ea7ec7619f50a23a7. The current sampling-mask padding and multimodal batch paths are preserved.

  • uv run --locked pytest -q tests/unit/orchestrator/test_batch.py: 36 passed on Python 3.12.
  • A 256-expert, top-k 8, one-row padding case assigns one route to each of eight contiguous EP ranks per layer.
  • A 256-expert, top-k 2, seven-row padding case produces 14 distinct routes per layer; per-expert counts differ by at most one and the eight-rank histogram is [1, 1, 2, 2, 2, 2, 2, 2] up to rank ordering.
  • A 256-expert, top-k 8, 33-row padding case crosses a full expert cycle while retaining distinct routes per row, per-expert skew of one, and exactly 33 assignments per EP rank.
  • A 512-expert case verifies uint8 to uint16 widening, exact preservation of sampled routes, row/layer rotation, and balanced aggregate EP assignment.
  • A supplemental CPU probe passed three cases combining routing replay, sampling masks, and objective-weight streams: original payloads remained intact, sampling-mask padding counts were zero, and padding contributed no objective weight.
  • Ruff check, Ruff format check, and git diff --check pass for the changed files.

No multi-GPU or DeepEP end-to-end training run was performed; the regression coverage validates the production packing payload and its dispatch-facing invariants on CPU.

@EazyReal
EazyReal force-pushed the fix/moe-routing-replay-padding branch from f4d8438 to 040b6b8 Compare August 23, 2026 00:03
@mikasenghaas

Copy link
Copy Markdown
Member

uh this is cool, we will check!

@EazyReal
EazyReal force-pushed the fix/moe-routing-replay-padding branch from 040b6b8 to d2ec61d Compare August 23, 2026 00:31
@MarioSieg

Copy link
Copy Markdown
Member

Amazing - looks good so far :)
Can you rebase onto main and fix the conflicts?

@EazyReal
EazyReal force-pushed the fix/moe-routing-replay-padding branch from d2ec61d to 4f343c0 Compare August 26, 2026 13:08
@EazyReal

Copy link
Copy Markdown
Contributor Author

Done!

Sequence packing appends loss-masked rows to router-replay batches, but zero-filled expert indices send every synthetic route through expert 0 and can hotspot one EP rank.

Spread padding routes across the full expert domain in final layout order, rotate assignments per layer, and widen compact payloads when needed. Preserve sampled routes and fail closed when the model expert count is unavailable.
@EazyReal
EazyReal force-pushed the fix/moe-routing-replay-padding branch from 4f343c0 to 893604c Compare September 30, 2026 00:56
@EazyReal

EazyReal commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor Author

@MarioSieg rebased onto current main and resolved the conflicts, preserving the new sampling-mask and multimodal paths.Could you take another look?

garrett361 added a commit that referenced this pull request Oct 20, 2026
…oid MoE hot spots (#4184)

This PR gives RL the same `pad_to_seq_len` flag that SFT supports
(#4160). The flag pads every packed row to `seq_len`, so torch.compile
and DeepGEMM stop recompiling on new lengths. Full-length padding makes
an existing MoE problem worse (identical pad tokens all route to the
same experts), so this PR also changes RL and SFT to pad with the row's
own tokens instead of a constant id.

- RL used to pad with token 1, and router replay padded with zero bytes,
which sent every pad slot to expert 0. This PR pads text rows with their
own tokens and replay with their real routes.
- Multimodal rows keep a constant pad id, because a repeated image
placeholder would have no image feature to receive.
- This PR supersedes #3932 / #4149 (SFT pad content, credit Mika).
Please keep the `Co-authored-by: Mika Senghaas` trailer when squashing.
Related: #3350.

We ran FP8 e2e checks on one H200 node per run, each with an empty
DeepGEMM cache (harness in a31524e):

| Run | Dynamo recompiles per rank, total (after step 1) | DeepGEMM
compiles, total (after step 1) |
| --- | --- | --- |
| SFT GLM-4.5-Air 4L `--data.pad-to-seq-len` | 1 (0) | 22 (0) |
| SFT GLM-4.5-Air 4L | 3 (0) | 34 (7) |
| RL Qwen3-30B-A3B + replay `--orchestrator.pad-to-seq-len` | 0 (0) | 17
(0) |
| RL Qwen3-30B-A3B + replay | 1 (0) | 54 (28) |

The flag only makes the row length static: the number of micro batches
per step, `max_seqlen`, and multimodal shapes still vary. The throughput
and MFU metrics count padding, so they are not comparable with and
without the flag.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Mika Senghaas <mika@primeintellect.ai>

Copy link
Copy Markdown
Contributor Author

Closing as superseded by #4184 for the original zero-filled routing-replay padding hotspot. That PR repeats real routes and tokens, while this PR synthesizes balanced expert assignments; the stronger balance guarantees here could be evaluated separately if benchmarks justify a follow-up.

The original diagnosis and proposed fix remain documented here. I’ve requested explicit attribution and consideration of coauthor credit on #4184: #4184 (comment). Closing this PR does not resolve that attribution request.

@EazyReal EazyReal closed this Oct 25, 2026
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.

3 participants