Skip to content

perf(moe_ep): add a separate scale ring to the SM90 NVFP4 CuTe DSL backend - #1

Closed
ruoqianguo wants to merge 1 commit into
codex/sm90-nvfp4-fp8-megamoefrom
codex/sm90-nvfp4-fp8-scale-ring
Closed

ruoqianguo wants to merge 1 commit into
codex/sm90-nvfp4-fp8-megamoefrom
codex/sm90-nvfp4-fp8-scale-ring

Conversation

@ruoqianguo

@ruoqianguo ruoqianguo commented Oct 22, 2026 •

Copy link
Copy Markdown
Owner

Superseded by the upstream follow-up: flashinfer-ai/flashinfer#7542, based on main after flashinfer-ai#6999 merged. This fork PR is kept as the original review record.


📌 Description

This PR is stacked on #6999. For the measured N64/K256 configurations, NVFP4 has three AB stages while MXFP4 with compact buffers has four. NVFP4 stores twice as many weight scales (K16 versus K32). Moving scales into a two-slot ring (nvfp4_sf_stages=2) frees space for a fourth AB stage.

Sf2 candidates must satisfy supported geometry, protocol and resource constraints, without GPU-name or token-count checks. The kernel rejects incompatible layouts. Only T512/T1024 defaults change to sf2/R1; the end-to-end test verifies byte-identical output against PR1 sf0.

Performance and reproduction

The table compares sf2 with PR1 sf0 defaults and MX main defaults with manual compact=True. Negative deltas mean sf2 is faster.

T/rank PR1 sf0 µs sf2 µs MX µs Paired sf2/sf0 Δ Paired sf2/MX Δ
512 1232.6 1189.6 1192.8 -3.68% -0.38%
1024 1607.2 1566.6 1615.7 -2.75% -3.00%

We measured MegaMoE plus top-k reduction on 4×H200 with EP4/H7168/I3072/E384/top-6/clamp10. Each block takes the maximum of four rank medians. Paired ratios are summarized across three rounds and three fresh processes, without dividing independent latency medians. SM clocks were set to 1830 MHz. Software power-cap events were recorded, so a constant clock in every timed block is not guaranteed.

All nine T512 rounds were retained; fresh-process sf2/sf0 medians ranged from -4.83% to -3.16%.

To reproduce PR1, export its defaults first. Setting only nvfp4_sf_stages=0 is insufficient because sf2 entries also change pull-buffer and LUT settings:

python - <<'PYEXPORT'
import json
import runpy

data = runpy.run_path(
    "flashinfer/moe_ep/kernel_src/sm90/pull_style_cutedsl_megakernel/shim/nvfp4_candidate_data.py"
)
profiles = {
    str(tokens): {
        "tactic": dict(data["NVFP4_SF0_CANDIDATE_SEEDS"][spec[0]]),
        "config": {
            "nvfp4_kperm": 64,
            "nvfp4_fc1_k256_overlap": spec[-1],
        },
    }
    for tokens, spec in data["_DEFAULTS"].items()
}
with open("nvfp4-pr1-sf0-defaults.json", "x") as output:
    json.dump({"per_token": profiles}, output, indent=2)
    output.write("\n")
PYEXPORT
nv_bench_root="$(mktemp -d -p . sm90-pr2-current-XXXXXX)"
for fresh in 1 2 3; do
  FLASHINFER_MOE_EP_KNOB_CACHE="$(pwd)/${nv_bench_root}/knob-${fresh}.json" \
  torchrun --standalone --nproc_per_node=4 benchmarks/bench_moe_ep_sm90_nvfp4.py \
    --tokens 512 1024 --hidden 7168 --intermediate 3072 --experts 384 --top-k 6 \
    --seed 1234 --nv-kperm 64 --nv-overlap auto --mx-compact \
    --nv-reference-knobs-json nvfp4-pr1-sf0-defaults.json \
    --rounds 3 --warmup 10 --iters 50 --padding-us 300 --cooldown-seconds 5 \
    --output "${nv_bench_root}/fresh-${fresh}.json" || exit $?
done

🔍 Related Issues

Base: flashinfer-ai#6999. Separate CUDA implementation: #6343.

🚀 Pull Request Checklist

✅ Pre-commit Checks

  • I have installed pre-commit by running pip install pre-commit (or used your preferred method).
  • I have installed the hooks with pre-commit install.
  • I have run the hooks manually with pre-commit run --all-files and fixed any reported issues.

🧪 Tests

  • Tests have been added or updated as needed.
  • All tests are passing (unittest, etc.).

The existing NCCL-EP high-throughput test (tests/moe_ep/test_moe_ep_cudagraph_multirank.py, high_throughput) also fails on unmodified main (eed63cd) in our 4×H200 environment; it is unrelated to this PR.

Default MXFP4/FP8/BF16 cubins match tested main byte-for-byte. The four-format EP4 end-to-end, host/unit and registration tests passed on 4×H200.

EP4 regression reproduction:

for dtype in nvfp4 mxfp4 fp8 bf16; do
  torchrun --standalone --nproc_per_node=4 -m pytest \
    "tests/moe_ep/test_moe_ep_sm90_pull_${dtype}_mega_multirank.py" \
    -vv -ra -rs --tb=short --full -m arch_hopper || exit $?
done

🔬 Experimental Track

  • This PR is experimental: it adds or changes code under flashinfer/experimental/ and/or an @flashinfer_experimental_api. Tracking issue: #
    • The tracking issue names an owner, the reason for the experimental path, and a graduation plan with a target release.
    • Core changes are limited to a thin entry point (signature, shared validation, feature-gate check, backend selection, handoff).
    • Tests live in tests/experimental/ and were validated on the intended hardware; a runnable example is included.
    • Nothing is registered in flashinfer/aot.py, and no experimental backend is reachable from backend="auto" without FLASHINFER_ALLOW_EXPERIMENTAL_AUTO_BACKENDS=1. (Calling an @flashinfer_experimental_api or naming a backend explicitly is itself the opt-in and needs no environment variable.)
    • Test scope declared below. The experimental CI lane runs exactly these targets, so keep them as narrow as the change allows.
# One target per line: a directory or a file. (A pytest ::selector is not
# supported -- the sharding runner cannot consume one.) Must be under
# tests/experimental/ and must exist. Delete these comment lines and add yours, e.g.
#
#   tests/experimental/test_my_backend.py
#   tests/experimental/my_backend/
#
# Declaring the whole tree (tests/experimental/) is allowed but means every
# experimental PR pays for every other feature's tests, in every matrix cell.

Reviewer Notes

Review scale-slot ownership, cross-tile state and memory accounting. This PR is stacked on flashinfer-ai/flashinfer#6999 and will be submitted upstream after PR1 is merged.

@ruoqianguo
ruoqianguo force-pushed the codex/sm90-nvfp4-fp8-scale-ring branch 2 times, most recently from 35aaabd to 3fdcd47 Compare October 23, 2026 12:53
@ruoqianguo ruoqianguo changed the title perf(moe_ep): add an independent NVFP4 weight-scale ring perf(moe_ep): add a separate scale ring to the SM90 NVFP4 CuTe DSL backend Oct 26, 2026
@ruoqianguo
ruoqianguo force-pushed the codex/sm90-nvfp4-fp8-scale-ring branch from 3fdcd47 to 387ffec Compare October 26, 2026 08:53
@ruoqianguo
ruoqianguo marked this pull request as ready for review October 26, 2026 09:22
jiahanc pushed a commit to flashinfer-ai/flashinfer that referenced this pull request Oct 27, 2026
<!-- .github/pull_request_template.md -->

## 📌 Description

This adds CuTe DSL NVFP4×FP8 to unified `moe_ep.MoEEpLayer`;
[#6343](#6343) provides
the separate `flashinfer.megamoe` CUDA API.

NV inherits MXFP4 frontend/kernel classes, overriding weight-format,
conversion and scheduling behavior with separate cache/workspace
identities. The default is `nvfp4_kperm=64`.

For H7168/I3072/E384/top-6/EP4, 13 capacities span 8–32768 tokens/rank.
Other capacities use the next larger entry, capped at 32768; other
shapes use heuristics. MX gains optional `compact_pull_buffer=True`,
disabled by default; MX auto/candidates are unchanged.

### Performance and reproduction

We compare NV defaults with MX main defaults with manual compact=True.
Positive means NV is slower.

| T/rank | NV µs | MX µs | Paired NV/MX Δ |
|---:|---:|---:|---:|
| 8 | 452.4 | 430.1 | +5.13% |
| 16 | 642.8 | 643.2 | -0.03% |
| 32 | 807.2 | 777.6 | +3.73% |
| 64 | 908.8 | 878.3 | +3.51% |
| 128 | 938.8 | 910.9 | +3.16% |
| 256 | 1014.7 | 990.7 | +2.42% |
| 512 | 1227.9 | 1191.2 | +3.08% |
| 1024 | 1607.8 | 1608.8 | -0.13% |
| 2048 | 2733.0 | 2868.6 | -4.92% |
| 4096 | 5020.7 | 5229.2 | -4.18% |
| 8192 | 9530.0 | 9845.9 | -3.26% |
| 16384 | 18507.6 | 19150.0 | -3.34% |
| 32768 | 36690.8 | 38506.6 | -4.80% |

We measured MegaMoE plus top-k reduction on 4×H200. Each block takes the
maximum of four rank medians. Paired ratios are summarized across three
rounds and three fresh processes. SM clocks were set to 1830 MHz.
Software power-cap events were recorded, so a constant clock in every
timed block is not guaranteed.

NV stores 5.9% more weight bytes, adding traffic. T512 observations were
retained: rounds ranged +2.71–13.08%, while process medians ranged
+2.89–3.67%.

```bash
nv_bench_root="$(mktemp -d -p . sm90-pr1-current-XXXXXX)"
for fresh in 1 2 3; do
  FLASHINFER_MOE_EP_KNOB_CACHE="$(pwd)/${nv_bench_root}/knob-${fresh}.json" \
  torchrun --standalone --nproc_per_node=4 benchmarks/bench_moe_ep_sm90_nvfp4.py \
    --tokens 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 \
    --hidden 7168 --intermediate 3072 --experts 384 --top-k 6 --seed 1234 \
    --nv-kperm 64 --nv-overlap auto --mx-compact \
    --rounds 3 --warmup 10 --iters 50 --padding-us 300 --cooldown-seconds 5 \
    --output "${nv_bench_root}/fresh-${fresh}.json" || exit $?
done
```

## 🔍 Related Issues

Stacked follow-up: ruoqianguo#1.

## 🚀 Pull Request Checklist

### ✅ Pre-commit Checks

- [x] I have installed `pre-commit` by running `pip install pre-commit`
(or used your preferred method).
- [ ] I have installed the hooks with `pre-commit install`.
- [x] I have run the hooks manually with `pre-commit run --all-files`
and fixed any reported issues.

## 🧪 Tests

- [x] Tests have been added or updated as needed.
- [ ] All tests are passing (`unittest`, etc.).

The existing NCCL-EP high-throughput test
(tests/moe_ep/test_moe_ep_cudagraph_multirank.py, `high_throughput`)
also fails on unmodified main (eed63cd) in our 4×H200 environment; it
is unrelated to this PR.

Default MXFP4/FP8/BF16 cubins match tested main byte-for-byte. The
four-format EP4 end-to-end, host/unit and registration tests passed. NV
requires relative L2<2.5% against FP32 with promoted operands. All 55
public auto candidates compiled and ran; a new layer reused the cache.
This was functional smoke, not per-candidate FP32/performance
qualification.

Regression:

```bash
for dtype in nvfp4 mxfp4 fp8 bf16; do
  torchrun --standalone --nproc_per_node=4 -m pytest \
    "tests/moe_ep/test_moe_ep_sm90_pull_${dtype}_mega_multirank.py" \
    -vv -ra -rs --tb=short --full -m arch_hopper || exit $?
done
```

## Reviewer Notes

Please review weight preprocessing and the `nvfp4_kperm` layout tags,
NV's inheritance from the MX classes and the hooks added to the MX/FP8
base classes, the default tactic table, and MX's optional
`compact_pull_buffer`. The sf2 scale ring is covered by the stacked
[PR2](ruoqianguo#1).

## 🔬 Experimental Track

<!-- Only for PRs submitted under the experimental policy
(CONTRIBUTING.md → "Experimental APIs and Backends").
     Leave this section untouched for normal PRs. -->

- [ ] This PR is **experimental**: it adds or changes code under
`flashinfer/experimental/` and/or an `@flashinfer_experimental_api`.
Tracking issue: #
- [ ] The tracking issue names an owner, the reason for the experimental
path, and a graduation plan with a target release.
- [ ] Core changes are limited to a thin entry point (signature, shared
validation, feature-gate check, backend selection, handoff).
- [ ] Tests live in `tests/experimental/` and were validated on the
intended hardware; a runnable example is included.
- [ ] Nothing is registered in `flashinfer/aot.py`, and no experimental
backend is reachable from `backend="auto"` without
`FLASHINFER_ALLOW_EXPERIMENTAL_AUTO_BACKENDS=1`. (Calling an
`@flashinfer_experimental_api` or naming a backend explicitly is itself
the opt-in and needs no environment variable.)
- [ ] **Test scope declared below.** The experimental CI lane runs
exactly these targets, so keep them as narrow as the change allows.

<!-- Required for experimental PRs. Replace the commented lines below
with your targets.
Do not delete the fence or change its `experimental-tests` tag — the
experimental-track
watcher reads it verbatim to decide which targets to ask CI for. -->

```experimental-tests
# One target per line: a directory or a file. (A pytest ::selector is not
# supported -- the sharding runner cannot consume one.) Must be under
# tests/experimental/ and must exist. Delete these comment lines and add yours, e.g.
#
#   tests/experimental/test_my_backend.py
#   tests/experimental/my_backend/
#
# Declaring the whole tree (tests/experimental/) is allowed but means every
# experimental PR pays for every other feature's tests, in every matrix cell.
```



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

<!-- coderabbit-ai-generated:v1 -->

## Summary by CodeRabbit

* **New Features**
* Added SM90 NVFP4 support for expert-parallel MegaMoE, including weight
preprocessing, configurable layouts, and automatic or custom tuning.
* Added options for K-permuted weights and FC1 scheduling, with
validation for incompatible configurations.
  * Added a distributed benchmark for measuring NVFP4 performance.
* **Documentation**
* Documented the backend’s numerical behavior, weight requirements,
configuration, tuning, and benchmark methodology.
* **Tests**
* Added multirank coverage for output accuracy, repeatability, layout
validation, and CUDA graph scheduling.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@ruoqianguo ruoqianguo closed this Oct 27, 2026
ruoqianguo pushed a commit that referenced this pull request Nov 5, 2026
…age match what the calls bind (flashinfer-ai#8623)

`flashinfer.experimental.cake_gdn_train_kcp` is the non-deterministic
GDN training package with key-context parallelism. Callers use its byte
queries (`gdn_workspace_layout_kcp`, `gdn_workspace_bytes_kcp`,
`gdn_saved_layout_kcp`, `gdn_comm_bytes_kcp`) to size a caller-held
`WorkspaceKcp` and to budget memory. These queries did not match what
the calls bind. On two ranks of a five-document pack at HV = 6 and P = 2
with crossing fragments, `gdn_workspace_layout_kcp` reported up to
2,162,688 B less than the workspace actually bound in the backward, and
up to 589,824 B less in the forward; in other contexts the queries
counted buffers the call never binds. The queries also did not model
several documented call contexts. This PR adds the missing terms and
contexts, removes the extra ones, and new tests check the queries
against the real host path at exact bytes.

The queries now report:

- At P > 1, the M_f^T tiles of crossing-out fragments in the c1 send
pool (new term `c1_send_mf`).
- With the fused walks at P > 1, `max(n_in, n_out)` more carry-plane
slots (new keyword `fused_walks`, the call's test knob; 1 is the shipped
form).
- The b1 pools at the larger of their two split forms, as the host sizes
them.
- For a saved backward on a caller-held workspace, the forward exchange
pools again until its adjoint exchange is done.
- The `P=` override in the workspace staging term.
- New `graph="replay"`: a captured call releases no buffer, so the
forward and backward figures count every pool and tape the call binds.
Like the call, the query refuses it with `reuse_recompute_tapes=True` /
`"auto"`.
- New `save_for_backward=`: a forward without a saved set, and the
backward that then replays the forward. After a fused forward, the
replayed forward binds the eight tapes `#1` re-writes, not ten, before
its c1 release.
- `boundary_mode="replay"`: S_in as a fresh tensor, and the replayed
forward's moment before the c1 release as `bwd.phase.replay_forward`.
- Kept-tape form (`reuse_recompute_tapes`) at P > 1 without
`save_transfer`: one backward staging plane, with the handed-over
M_seg^T plane counted in `bwd.kept_tapes` and `backward_transient`.
- The forward as the larger of `fwd.phase.prep` (`#1`) and
`fwd.phase.walk`.

The figures are for a workspace's first forward and backward. The docs
explain how later steps on a reused workspace compare with the
`graph="replay"` figure: equal for the replay form, and at most that
figure in the cases they name. The docs list `exchange="ring"` and the
`schedule="overlap"` test knob as not covered and give their extra terms
as bounds. `graph=`, `save_for_backward=` and `fused_walks=` exist only
on this package's query. Through the facade they need
`deterministic=False`.

The README's byte-query block now states the same rules. Its formula
cells use the padded state size: S_in is `n_in * s_pad`, and the owner's
summary pairs are `2 * s_owner * N_out`. The `gdn_comm_bytes_kcp`
formulas use `s_pad` / `s_owner` and the group totals. The validator
does not check a workspace's size, and the README no longer says it
does.

Tests (all CPU):

- An arena test runs the real host path with a recording workspace and
checks the query at tolerance 0. It covers two- and four-rank groups
with fragments that cross in and out, `graph="replay"`, forward-only
calls and their `saved=None` backward, the replay boundary, the
in-kernel L2 norm, and per-pool sizes. It also records the bytes bound
just before the replayed forward releases the c1 send pool, and checks
them against `bwd.phase.replay_forward` on every rank of a group that
exchanges.
- A measured kept-form checkpoint test at P = 2 (with and without
`save_transfer`, and with the norm) checks the pool sizes, the hand-off
bytes, the backward figure and `backward_transient`.
- A three-step reuse test checks what the docs say about later steps.
- A README tie test checks the saved-set table, including a padded owner
(HV = 48 on five ranks).
- An API test checks the facade route and the remaining differences
between the two packages' saved queries.
- Package suite: 435 passed, 115 skipped. Deterministic package suite:
289 passed, 85 skipped. Each of 49 mutations of the queries, each
reverting or breaking one modelled term, makes at least one new test
fail.

Query, documentation and test changes only (5 files, +1526 / -244); the
runtime, the kernels and the deterministic package are unchanged, so
there is no timing.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

<!-- coderabbit-ai-generated:v1 -->

## Summary by CodeRabbit

* **New Features**
* Workspace and saved-memory queries now account for graph modes, fused
or split execution, replay boundaries, saved-tensor choices, and segment
overrides.
* Workspace queries include additional staging, exchange, and
normalization buffers in their estimates.
* **Documentation**
* Clarified workspace sizing, saved-data behavior, replay details,
segment planning, and per-rank memory calculations.
  * Expanded guidance on byte-query options and graph-mode coverage.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Yingyi Huang <averyh@nvidia.com>
ruoqianguo pushed a commit that referenced this pull request Nov 5, 2026
…00 and SM103 (flashinfer-ai#8622)

This PR adds an L2-prefetching build of the mid forward to the
non-deterministic package of Cake's SiLU-gated RMSNorm training kernel
(`flashinfer.cake_rmsnorm_silu_gate_train` with `deterministic=False`).
On sm_100a and sm_103a, the mid forward now routes to that build. In the
new module, `cake_rmsnorm_silu_gate_train_87f0173e9583ad4fdd2a`, thread
0 also warms two later row blocks in L2, with one bulk prefetch per
tensor, wherever the inputs x and z hold their rows packed. The two
blocks are the CTA's next block and the CTA's first block one resident
wave later. The routing thresholds do not change: on these two
architectures, the mid forward serves inputs from 976 rows per SM up to
the long forward's 2400. The six shapes per GPU in Table 1 fall in that
range.

Every other module is FlashInfer main's code. The backward, the short
and long forwards, and every sm_107a route run the same code as before.
The forward modules' build settings now include the two prefetch
settings, so the long, mid (sm_107a) and short forward modules shipped
before get new names; the renamed modules are the same code under new
names.

| forward | name on FlashInfer main | name in this PR | architectures |
|---|---|---|---|
| long | `cake_rmsnorm_silu_gate_train_e0672c312c57421abe21` |
`cake_rmsnorm_silu_gate_train_7b7fac905aff1ddaa258` | sm_100a, sm_103a,
sm_107a |
| mid | `cake_rmsnorm_silu_gate_train_8bd481246a4b97382250` |
`cake_rmsnorm_silu_gate_train_b0eb3df9844d5b734850` | sm_107a |
| short | `cake_rmsnorm_silu_gate_train_55ff8a9d0ba6d83285b5` |
`cake_rmsnorm_silu_gate_train_de5df3c9a4a5a804fcf2` | sm_100a, sm_103a,
sm_107a |

The PR is one commit on FlashInfer main after PR flashinfer-ai#8556 (merge commit
7b20619). The "previous Cake" baseline
below is FlashInfer main's route, where the mid forward runs without the
prefetch. The A/B compared FlashInfer main at
61bc8b6 with the same tree plus this
PR's mid forward and routes. That commit predates PR flashinfer-ai#8556, which
changes no sm_100a or sm_103a route. In the measured tree, the new
module's sources are byte-identical to this PR's, and the unchanged
modules keep their old names.

A speedup is baseline us / new us, so a value above 1 means this PR is
faster. The table gives ranges (min-max) over the six shapes of Table 1.
For stepg_f32 and fwd + bwd, the ranges cover the ten shapes of Table 2:
those six, plus four shapes that run the same code in both trees.

| GPU | op | det Cake / new | strongest non-Cake / new | previous Cake /
new (A/B) |
|---|---|---|---|---|
| B200 | fwd | 1.086-1.116 | 0.990-1.049 | 1.068-1.090 |
| B200 | fwdg | 1.080-1.115 | 0.991-1.048 | 1.062-1.088 |
| B200 | bwdg | 1.111-1.180 | 1.122-1.166 | 0.9996-1.0002 |
| B200 | ckptg | 1.065-1.110 | 1.057-1.100 | 1.020-1.035 |
| B200 | stepg_f32 (10 shapes) | 1.036-1.112 | - | 0.9998-1.036 |
| B200 | fwd + bwd (10 shapes) | 1.107-1.157 | - | 0.9996-1.032 |
| GB300 | fwd | 1.101-1.147 | 1.003-1.107 | 1.068-1.121 |
| GB300 | fwdg | 1.098-1.144 | 0.998-1.102 | 1.065-1.121 |
| GB300 | bwdg | 1.081-1.170 | 1.075-1.124 | 1.000-1.0005 |
| GB300 | ckptg | 1.064-1.136 | 1.041-1.098 | 1.022-1.044 |
| GB300 | stepg_f32 (10 shapes) | 1.029-1.134 | - | 0.9997-1.046 |
| GB300 | fwd + bwd (10 shapes) | 1.057-1.157 | - | 0.9998-1.042 |

In the pre-registered A/B, all 24 cells per GPU whose code changes (fwd,
fwdg, ckptg and stepg_f32 at the six shapes) are faster than the
previous Cake route. bwdg runs the same code in both trees.
torch.compile is faster than the new forward at 5 of the 12 B200 forward
rows and at 1 of the 12 GB300 forward rows, each time by 1 % or less.
Every cell below 1x is listed under "Cells below 1x".

The kernel's other Cake variants are the deterministic package
`flashinfer.cake_rmsnorm_silu_gate_det_train` (the same API with
`deterministic=True`) and the FP32 weight-gradient output of the
non-deterministic package. Both packages ship on sm_100a, sm_103a and
sm_107a. This PR changes only the non-deterministic package's mid
forward on sm_100a and sm_103a, and sm_107a keeps its code.

## How the tables were measured

- Latency: CUPTI kernel time with cold L2 (FlashInfer's
`bench_gpu_time`), BF16 inputs. All times are in us.
- Table 1: the deterministic Cake kernel, the strongest non-Cake kernel
and new were measured in the same process. Each value is the median of
the per-round medians over 10 rounds.
- A/B values: the previous Cake and new (A/B) columns and all of Table 2
are medians of the pre-registered interleaved A/B, with 16 sequences and
160 processes per GPU model. The deterministic Cake values in the
stepg_f32 rows also come from the A/B.
- Strongest non-Cake kernel per row: the fastest of the following, with
torch 2.14.1+cu130 and Triton 3.8.0.
  - FLA 0.6.0 `rms_norm_gated` (`fla.modules.fused_norm_gate`).
  - mamba_ssm v2.3.2 `rmsnorm_fn` (`layernorm_gated`).
- torch.compile in default and max-autotune-no-cudagraphs modes, best of
5 fresh compiles each. `#k` names the fastest compile.
- The inductor-generated persistent-reduction Triton kernel of the FP32
formula, launched directly.
- Deterministic Cake: `flashinfer.cake_rmsnorm_silu_gate_det_train`,
unchanged by this PR.
- Operations:
- `fwd` is one eager forward call, and `fwdg` is the forward replayed
from a CUDA graph.
  - `bwdg` is the backward replayed from a CUDA graph.
- `ckptg` is the checkpointed step (2 x forward + backward) in one CUDA
graph, and `stepg_f32` is the same step with an FP32 dw.
  - `fwd + bwd` is fwdg + bwdg, derived.
- In Table 2, the first six shapes run the new module. 2048x48, 3009x48
(B200) / 3090x48 (GB300), 7400x48 (B200) / 7600x48 (GB300) and 16384x48
run the same code in both trees.

## Cells below 1x

- vs the strongest non-Cake kernel (Table 1), every forward row where
torch.compile is faster:
- B200 3010x48 fwdg: 23.136 us (torch.compile max-autotune-no-cudagraphs
flashinfer-ai#5) vs 23.231 us new, 0.996
- B200 3157x48 fwd: 23.424 us (torch.compile max-autotune-no-cudagraphs
flashinfer-ai#5) vs 23.503 us new, 0.997
- B200 3157x48 fwdg: 23.44 us (torch.compile max-autotune-no-cudagraphs
flashinfer-ai#4) vs 23.648 us new, 0.991
- B200 8192x32 fwd: 36.895 us (torch.compile max-autotune-no-cudagraphs
flashinfer-ai#3) vs 37.264 us new, 0.990
- B200 8192x32 fwdg: 37.024 us (torch.compile max-autotune-no-cudagraphs
flashinfer-ai#4) vs 37.376 us new, 0.991
- GB300 3157x48 fwdg: 22.032 us (torch.compile default #1) vs 22.08 us
new, 0.998
- vs the deterministic Cake kernel: none.
- vs the previous Cake route (A/B), only at cells that run the same code
in both trees:
  - B200 bwdg (Table 1): 3010x48 0.9996, 4097x48 0.99999, 6000x48 0.9998
- B200 (Table 2): 2048x48 ckptg 0.999, 3009x48 fwd + bwd 0.9996, 7400x48
ckptg 0.99996, 7400x48 stepg_f32 0.9998, 16384x48 stepg_f32 0.9998
- GB300 (Table 2): 2048x48 stepg_f32 0.9997, 3090x48 stepg_f32 0.9999,
3090x48 fwd + bwd 0.9998, 16384x48 ckptg 0.9998

## Results on B200 (sm_100a, 148 SMs)

- GPU: NVIDIA B200, sm_100a, compute capability 10.0, 148 SMs, driver
580.82.07.
- CUDA: 13.4 (nvcc Build cuda_13.4.r13.4/compiler.38855100_0); PyTorch
2.14.1+cu130 (CUDA 13.0); Triton 3.8.0; Python 3.12.15.

### Table 1 (B200): new vs the deterministic Cake kernel, the strongest
non-Cake kernel and the previous Cake route

| T x H | op | det Cake us | strongest non-Cake us | strongest non-Cake
kernel | new us | previous Cake us (A/B) | new us (A/B) | det / new |
non-Cake / new | previous / new (A/B) |
|---|---|---|---|---|---|---|---|---|---|---|
| 3010x48 | fwd | 24.992 | 23.039 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#5 | 23.008 | 24.288 | 22.752 | 1.086 | 1.001
| 1.068 |
| 3010x48 | fwdg | 25.087 | 23.136 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#5 | 23.231 | 24.337 | 22.912 | 1.080 | 0.996
| 1.062 |
| 3010x48 | bwdg | 49.712 | 49.104 | FLA rms_norm_gated | 42.112 |
42.048 | 42.064 | 1.180 | 1.166 | 0.9996 |
| 3010x48 | ckptg | 95.071 | 92.751 | FLA rms_norm_gated | 87.167 |
88.328 | 86.608 | 1.091 | 1.064 | 1.020 |
| 3010x48 | stepg_f32 | 94.812 (A/B) | not measured | - | - | 88.040 |
86.424 | 1.097 (A/B) | n/a | 1.019 |
| 3157x48 | fwd | 26.08 | 23.424 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#5 | 23.503 | 25.584 | 23.728 | 1.110 | 0.997
| 1.078 |
| 3157x48 | fwdg | 26.271 | 23.44 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#4 | 23.648 | 25.744 | 23.848 | 1.111 | 0.991
| 1.080 |
| 3157x48 | bwdg | 48.736 | 48.975 | FLA rms_norm_gated | 43.632 |
43.792 | 43.784 | 1.117 | 1.122 | 1.0002 |
| 3157x48 | ckptg | 95.647 | 94.943 | FLA rms_norm_gated | 89.807 |
92.336 | 90.168 | 1.065 | 1.057 | 1.024 |
| 3157x48 | stepg_f32 | 95.864 (A/B) | not measured | - | - | 92.145 |
90.215 | 1.063 (A/B) | n/a | 1.021 |
| 4097x48 | fwd | 32.480 | 29.664 | torch.compile default flashinfer-ai#2 | 29.12 |
31.52 | 29.216 | 1.115 | 1.019 | 1.079 |
| 4097x48 | fwdg | 32.544 | 29.904 | torch.compile default flashinfer-ai#3 | 29.296 |
31.6 | 29.376 | 1.111 | 1.021 | 1.076 |
| 4097x48 | bwdg | 59.375 | 60.639 | FLA rms_norm_gated | 53.423 |
53.543 | 53.544 | 1.111 | 1.135 | 0.99999 |
| 4097x48 | ckptg | 118.607 | 119.199 | FLA rms_norm_gated | 110.103 |
113.448 | 110.311 | 1.077 | 1.083 | 1.028 |
| 4097x48 | stepg_f32 | 119.512 (A/B) | not measured | - | - | 113.420 |
110.360 | 1.083 (A/B) | n/a | 1.028 |
| 8192x32 | fwd | 41.6 | 36.895 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#3 | 37.264 | 40.544 | 37.184 | 1.116 | 0.990
| 1.090 |
| 8192x32 | fwdg | 41.663 | 37.024 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#4 | 37.376 | 40.632 | 37.344 | 1.115 | 0.991
| 1.088 |
| 8192x32 | bwdg | 75.519 | 76.207 | FLA rms_norm_gated | 66.623 |
66.824 | 66.816 | 1.134 | 1.144 | 1.0001 |
| 8192x32 | ckptg | 152.271 | 152.127 | FLA rms_norm_gated | 138.479 |
143.544 | 138.712 | 1.100 | 1.099 | 1.035 |
| 8192x32 | stepg_f32 | 153.080 (A/B) | not measured | - | - | 143.728 |
138.784 | 1.103 (A/B) | n/a | 1.036 |
| 6000x48 | fwd | 45.183 | 42.015 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#2 | 40.655 | 44.208 | 40.800 | 1.111 | 1.033
| 1.084 |
| 6000x48 | fwdg | 45.343 | 42.032 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#5 | 40.816 | 44.304 | 40.928 | 1.111 | 1.030
| 1.082 |
| 6000x48 | bwdg | 83.327 | 82.287 | FLA rms_norm_gated | 72.704 |
72.608 | 72.624 | 1.146 | 1.132 | 0.9998 |
| 6000x48 | ckptg | 166.959 | 166.719 | FLA rms_norm_gated | 151.583 |
156.704 | 151.688 | 1.101 | 1.100 | 1.033 |
| 6000x48 | stepg_f32 | 167.696 (A/B) | not measured | - | - | 156.472 |
151.592 | 1.106 (A/B) | n/a | 1.032 |
| 7399x48 | fwd | 54.304 | 51.136 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#5 | 48.752 | 52.720 | 48.904 | 1.114 | 1.049
| 1.078 |
| 7399x48 | fwdg | 54.336 | 51.087 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#4 | 48.768 | 52.848 | 48.992 | 1.114 | 1.048
| 1.079 |
| 7399x48 | bwdg | 98.975 | 97.887 | FLA rms_norm_gated | 86.752 |
86.988 | 86.984 | 1.141 | 1.128 | 1.00004 |
| 7399x48 | ckptg | 200.51 | 198.078 | FLA rms_norm_gated | 180.655 |
188.176 | 181.752 | 1.110 | 1.096 | 1.035 |
| 7399x48 | stepg_f32 | 201.944 (A/B) | not measured | - | - | 188.079 |
181.656 | 1.112 (A/B) | n/a | 1.035 |

### Table 2 (B200): full step, previous Cake route vs new (A/B medians)

| T x H | rows | op | previous Cake us | new us | previous / new | det
Cake us | det / new |
|---|---|---|---|---|---|---|---|
| 3010x48 | 144480 | ckptg | 88.328 | 86.608 | 1.020 | 94.952 | 1.096 |
| 3010x48 | 144480 | stepg_f32 | 88.040 | 86.424 | 1.019 | 94.812 |
1.097 |
| 3010x48 | 144480 | fwd + bwd | 66.385 | 64.976 | 1.022 | 75.184 |
1.157 |
| 3157x48 | 151536 | ckptg | 92.336 | 90.168 | 1.024 | 96.16 | 1.066 |
| 3157x48 | 151536 | stepg_f32 | 92.145 | 90.215 | 1.021 | 95.864 |
1.063 |
| 3157x48 | 151536 | fwd + bwd | 69.536 | 67.632 | 1.028 | 74.960 |
1.108 |
| 4097x48 | 196656 | ckptg | 113.448 | 110.311 | 1.028 | 119.168 | 1.080
|
| 4097x48 | 196656 | stepg_f32 | 113.420 | 110.360 | 1.028 | 119.512 |
1.083 |
| 4097x48 | 196656 | fwd + bwd | 85.143 | 82.920 | 1.027 | 92.712 |
1.118 |
| 8192x32 | 262144 | ckptg | 143.544 | 138.712 | 1.035 | 153.016 | 1.103
|
| 8192x32 | 262144 | stepg_f32 | 143.728 | 138.784 | 1.036 | 153.080 |
1.103 |
| 8192x32 | 262144 | fwd + bwd | 107.457 | 104.160 | 1.032 | 117.768 |
1.131 |
| 6000x48 | 288000 | ckptg | 156.704 | 151.688 | 1.033 | 167.760 | 1.106
|
| 6000x48 | 288000 | stepg_f32 | 156.472 | 151.592 | 1.032 | 167.696 |
1.106 |
| 6000x48 | 288000 | fwd + bwd | 116.912 | 113.552 | 1.030 | 128.831 |
1.135 |
| 7399x48 | 355152 | ckptg | 188.176 | 181.752 | 1.035 | 202.072 | 1.112
|
| 7399x48 | 355152 | stepg_f32 | 188.079 | 181.656 | 1.035 | 201.944 |
1.112 |
| 7399x48 | 355152 | fwd + bwd | 139.836 | 135.976 | 1.028 | 154.136 |
1.134 |
| 2048x48 | 98304 | ckptg | 63.512 | 63.560 | 0.999 | 65.944 | 1.037 |
| 2048x48 | 98304 | stepg_f32 | 62.936 | 62.896 | 1.001 | 65.168 | 1.036
|
| 2048x48 | 98304 | fwd + bwd | 48.432 | 48.432 | 1.0 | 53.616 | 1.107 |
| 3009x48 | 144432 | ckptg | 90.120 | 90.048 | 1.001 | 95.856 | 1.065 |
| 3009x48 | 144432 | stepg_f32 | 89.712 | 89.656 | 1.001 | 95.256 |
1.062 |
| 3009x48 | 144432 | fwd + bwd | 67.248 | 67.272 | 0.9996 | 74.992 |
1.115 |
| 7400x48 | 355200 | ckptg | 183.161 | 183.168 | 0.99996 | 201.863 |
1.102 |
| 7400x48 | 355200 | stepg_f32 | 182.856 | 182.888 | 0.9998 | 201.816 |
1.103 |
| 7400x48 | 355200 | fwd + bwd | 137.136 | 137.072 | 1.0005 | 154.064 |
1.124 |
| 16384x48 | 786432 | ckptg | 374.745 | 374.609 | 1.0004 | 416.543 |
1.112 |
| 16384x48 | 786432 | stepg_f32 | 374.809 | 374.895 | 0.9998 | 416.375 |
1.111 |
| 16384x48 | 786432 | fwd + bwd | 278.420 | 278.280 | 1.001 | 310.144 |
1.114 |

## Results on GB300 (sm_103a, 152 SMs)

- GPU: NVIDIA GB300, sm_103a, compute capability 10.3, 152 SMs, driver
580.159.03.
- CUDA: 13.4 (nvcc Build cuda_13.4.r13.4/compiler.38855100_0); PyTorch
2.14.1+cu130 (CUDA 13.0); Triton 3.8.0; Python 3.14.8.

### Table 1 (GB300): new vs the deterministic Cake kernel, the strongest
non-Cake kernel and the previous Cake route

| T x H | op | det Cake us | strongest non-Cake us | strongest non-Cake
kernel | new us | previous Cake us (A/B) | new us (A/B) | det / new |
non-Cake / new | previous / new (A/B) |
|---|---|---|---|---|---|---|---|---|---|---|
| 3091x48 | fwd | 23.776 | 21.696 | torch.compile default #1 | 21.6 |
23.537 | 21.504 | 1.101 | 1.004 | 1.095 |
| 3091x48 | fwdg | 23.841 | 21.776 | torch.compile default #1 | 21.720 |
23.621 | 21.696 | 1.098 | 1.003 | 1.089 |
| 3091x48 | bwdg | 46.241 | 47.072 | FLA rms_norm_gated | 42.464 |
42.496 | 42.496 | 1.089 | 1.109 | 1.0 |
| 3091x48 | ckptg | 89.872 | 88.032 | FLA rms_norm_gated | 84.432 |
86.664 | 84.800 | 1.064 | 1.043 | 1.022 |
| 3091x48 | stepg_f32 | 89.508 (A/B) | not measured | - | - | 86.121 |
84.352 | 1.061 (A/B) | n/a | 1.021 |
| 3157x48 | fwd | 24.512 | 21.984 | torch.compile default #1 | 21.920 |
23.768 | 22.177 | 1.118 | 1.003 | 1.072 |
| 3157x48 | fwdg | 24.704 | 22.032 | torch.compile default #1 | 22.08 |
23.904 | 22.368 | 1.119 | 0.998 | 1.069 |
| 3157x48 | bwdg | 47.536 | 46.993 | FLA rms_norm_gated | 43.552 |
43.544 | 43.536 | 1.091 | 1.079 | 1.0002 |
| 3157x48 | ckptg | 91.529 | 88.784 | FLA rms_norm_gated | 85.249 |
87.968 | 85.825 | 1.074 | 1.041 | 1.025 |
| 3157x48 | stepg_f32 | 90.888 (A/B) | not measured | - | - | 87.568 |
85.593 | 1.062 (A/B) | n/a | 1.023 |
| 4097x48 | fwd | 30.688 | 28.464 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#2 | 26.977 | 29.456 | 27.592 | 1.138 | 1.055
| 1.068 |
| 4097x48 | fwdg | 30.848 | 28.224 | torch.compile default #1 | 27.2 |
29.569 | 27.760 | 1.134 | 1.038 | 1.065 |
| 4097x48 | bwdg | 57.216 | 57.665 | FLA rms_norm_gated | 52.928 |
52.864 | 52.864 | 1.081 | 1.089 | 1.0 |
| 4097x48 | ckptg | 113.241 | 111.040 | FLA rms_norm_gated | 105.008 |
108.448 | 104.848 | 1.078 | 1.057 | 1.034 |
| 4097x48 | stepg_f32 | 113.112 (A/B) | not measured | - | - | 108.168 |
104.472 | 1.083 (A/B) | n/a | 1.035 |
| 8192x32 | fwd | 39.008 | 37.648 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#3 | 34.016 | 38.4 | 34.24 | 1.147 | 1.107 |
1.121 |
| 8192x32 | fwdg | 39.072 | 37.664 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#3 | 34.176 | 38.528 | 34.368 | 1.143 | 1.102
| 1.121 |
| 8192x32 | bwdg | 72.352 | 70.064 | FLA rms_norm_gated | 65.184 |
65.216 | 65.185 | 1.110 | 1.075 | 1.0005 |
| 8192x32 | ckptg | 144.464 | 140.400 | FLA rms_norm_gated | 130.577 |
136.872 | 131.284 | 1.106 | 1.075 | 1.043 |
| 8192x32 | stepg_f32 | 145.176 (A/B) | not measured | - | - | 136.904 |
131.216 | 1.106 (A/B) | n/a | 1.043 |
| 6000x48 | fwd | 42.625 | 38.976 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#3 | 37.472 | 41.408 | 37.28 | 1.138 | 1.040
| 1.111 |
| 6000x48 | fwdg | 42.688 | 39.120 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#3 | 37.632 | 41.536 | 37.360 | 1.134 | 1.040
| 1.112 |
| 6000x48 | bwdg | 79.089 | 76.832 | FLA rms_norm_gated | 70.049 |
70.208 | 70.208 | 1.129 | 1.097 | 1.0 |
| 6000x48 | ckptg | 158.385 | 153.409 | FLA rms_norm_gated | 142.257 |
148.04 | 142.352 | 1.113 | 1.078 | 1.040 |
| 6000x48 | stepg_f32 | 159.305 (A/B) | not measured | - | - | 147.888 |
142.328 | 1.119 (A/B) | n/a | 1.039 |
| 7599x48 | fwd | 52.385 | 48.577 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#3 | 45.761 | 51.064 | 46.304 | 1.145 | 1.062
| 1.103 |
| 7599x48 | fwdg | 52.512 | 48.576 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#3 | 45.888 | 51.2 | 46.392 | 1.144 | 1.059 |
1.104 |
| 7599x48 | bwdg | 96.960 | 93.136 | FLA rms_norm_gated | 82.865 |
83.136 | 83.136 | 1.170 | 1.124 | 1.000003 |
| 7599x48 | ckptg | 195.441 | 188.801 | FLA rms_norm_gated | 172.017 |
180.288 | 172.744 | 1.136 | 1.098 | 1.044 |
| 7599x48 | stepg_f32 | 195.801 (A/B) | not measured | - | - | 180.480 |
172.592 | 1.134 (A/B) | n/a | 1.046 |

### Table 2 (GB300): full step, previous Cake route vs new (A/B medians)

| T x H | rows | op | previous Cake us | new us | previous / new | det
Cake us | det / new |
|---|---|---|---|---|---|---|---|
| 3091x48 | 148368 | ckptg | 86.664 | 84.800 | 1.022 | 90.084 | 1.062 |
| 3091x48 | 148368 | stepg_f32 | 86.121 | 84.352 | 1.021 | 89.508 |
1.061 |
| 3091x48 | 148368 | fwd + bwd | 66.117 | 64.192 | 1.030 | 70.560 |
1.099 |
| 3157x48 | 151536 | ckptg | 87.968 | 85.825 | 1.025 | 91.624 | 1.068 |
| 3157x48 | 151536 | stepg_f32 | 87.568 | 85.593 | 1.023 | 90.888 |
1.062 |
| 3157x48 | 151536 | fwd + bwd | 67.448 | 65.904 | 1.023 | 71.64 | 1.087
|
| 4097x48 | 196656 | ckptg | 108.448 | 104.848 | 1.034 | 113.064 | 1.078
|
| 4097x48 | 196656 | stepg_f32 | 108.168 | 104.472 | 1.035 | 113.112 |
1.083 |
| 4097x48 | 196656 | fwd + bwd | 82.433 | 80.624 | 1.022 | 87.848 |
1.090 |
| 8192x32 | 262144 | ckptg | 136.872 | 131.284 | 1.043 | 145.472 | 1.108
|
| 8192x32 | 262144 | stepg_f32 | 136.904 | 131.216 | 1.043 | 145.176 |
1.106 |
| 8192x32 | 262144 | fwd + bwd | 103.744 | 99.553 | 1.042 | 111.776 |
1.123 |
| 6000x48 | 288000 | ckptg | 148.04 | 142.352 | 1.040 | 159.216 | 1.118
|
| 6000x48 | 288000 | stepg_f32 | 147.888 | 142.328 | 1.039 | 159.305 |
1.119 |
| 6000x48 | 288000 | fwd + bwd | 111.744 | 107.568 | 1.039 | 122.336 |
1.137 |
| 7599x48 | 364752 | ckptg | 180.288 | 172.744 | 1.044 | 195.913 | 1.134
|
| 7599x48 | 364752 | stepg_f32 | 180.480 | 172.592 | 1.046 | 195.801 |
1.134 |
| 7599x48 | 364752 | fwd + bwd | 134.336 | 129.528 | 1.037 | 149.8 |
1.157 |
| 2048x48 | 98304 | ckptg | 59.200 | 59.136 | 1.001 | 62.872 | 1.063 |
| 2048x48 | 98304 | stepg_f32 | 58.632 | 58.648 | 0.9997 | 61.912 |
1.056 |
| 2048x48 | 98304 | fwd + bwd | 45.28 | 45.28 | 1.0 | 51.696 | 1.142 |
| 3090x48 | 148320 | ckptg | 87.860 | 87.824 | 1.0004 | 90.384 | 1.029 |
| 3090x48 | 148320 | stepg_f32 | 87.160 | 87.168 | 0.9999 | 89.704 |
1.029 |
| 3090x48 | 148320 | fwd + bwd | 66.352 | 66.364 | 0.9998 | 70.144 |
1.057 |
| 7600x48 | 364800 | ckptg | 176.824 | 176.808 | 1.0001 | 195.873 |
1.108 |
| 7600x48 | 364800 | stepg_f32 | 176.288 | 176.232 | 1.0003 | 195.793 |
1.111 |
| 7600x48 | 364800 | fwd + bwd | 131.92 | 131.916 | 1.00003 | 149.56 |
1.134 |
| 16384x48 | 786432 | ckptg | 350.528 | 350.608 | 0.9998 | 391.449 |
1.116 |
| 16384x48 | 786432 | stepg_f32 | 350.744 | 350.713 | 1.0001 | 390.961 |
1.115 |
| 16384x48 | 786432 | fwd + bwd | 261.417 | 261.401 | 1.0001 | 291.065 |
1.113 |


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

<!-- coderabbit-ai-generated:v1 -->

## Summary by CodeRabbit

* **New Features**
* Added support for RMSNorm with SiLU gating on another GPU
architecture.
* **Performance**
* Updated kernel paths for supported architectures with
architecture-specific execution tuning and memory prefetching, helping
improve performance across different workloads. Short, mid-sized, and
long inputs continue to use tailored paths.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Yingyi Huang <averyh@nvidia.com>
ruoqianguo pushed a commit that referenced this pull request Nov 5, 2026
…ashinfer-ai#8656)

This PR switches the sm_107a mid forward of the non-deterministic
package of Cake's SiLU-gated RMSNorm training kernel
(`flashinfer.cake_rmsnorm_silu_gate_train` with `deterministic=False`)
to `cake_rmsnorm_silu_gate_train_87f0173e9583ad4fdd2a`. That is the
L2-prefetching module sm_100a and sm_103a already run. In it, thread 0
also warms two later row blocks in L2, with one bulk prefetch per
tensor, wherever the inputs x and z hold their rows packed. The two
blocks are the CTA's next block and the CTA's first block one resident
wave later. The sm_107a routing thresholds and grid do not change: the
mid forward serves inputs from 800 rows per SM up to the long forward's
1740. The five shapes in Table 1 fall in that range.

The module this replaces,
`cake_rmsnorm_silu_gate_train_b0eb3df9844d5b734850`, is the same
128-thread build without the prefetch. Nothing routes to it anymore, so
this PR removes it. It is the "previous Cake" baseline below. Every
other module and route is FlashInfer main's code: the backward, the
short and long forwards, and every sm_100a and sm_103a route run the
same code as before.

The PR is one commit on FlashInfer main after PR flashinfer-ai#8622. The A/B compared
two FlashInfer trees: one whose sm_107a mid forward runs without the
prefetch, and the same tree plus this PR's sm_107a route. In the
measured tree, the new module's sources are byte-identical to this PR's.

A speedup is baseline us / new us, so a value above 1 means this PR is
faster. The table gives ranges (min-max) over the five shapes of Table 1
on R200 (sm_107a, 212 SMs), CUDA 13.4. For stepg_f32 and fwd + bwd, the
ranges cover the twelve shapes of Table 2: those five, plus seven shapes
that run the same code in both trees.

| op | det Cake / new | strongest non-Cake / new | previous Cake / new
(A/B) |
|---|---|---|---|
| fwd | 1.119-1.141 | 1.071-1.080 | 1.113-1.136 |
| fwdg | 1.131-1.142 | 1.047-1.077 | 1.111-1.136 |
| bwdg | 1.081-1.163 | 1.097-1.119 | 0.9998-1.0002 |
| ckptg | 1.115-1.151 | 1.070-1.084 | 1.046-1.060 |
| stepg_f32 (12 shapes) | 1.068-1.218 | - | 0.9996-1.061 |
| fwd + bwd (12 shapes) | 1.062-1.197 | - | 0.998-1.045 |

In the pre-registered A/B, all 20 cells whose code changes (fwd, fwdg,
ckptg and stepg_f32 at the five shapes) are faster than the previous
Cake route. bwdg runs the same code in both trees. Neither the strongest
non-Cake kernel (Table 1) nor the deterministic Cake kernel (Tables 1
and 2) is faster than new on any row. Every cell below 1x is a same-code
cell against the previous Cake route, each by less than 0.3 %, and every
one is listed under "Cells below 1x".

The kernel's other Cake variants are the deterministic package
`flashinfer.cake_rmsnorm_silu_gate_det_train` (the same API with
`deterministic=True`) and the FP32 weight-gradient output of the
non-deterministic package. Both packages ship on sm_100a, sm_103a and
sm_107a. sm_100a and sm_103a have run this mid forward since PR flashinfer-ai#8622,
and this PR changes only the non-deterministic package's mid forward on
sm_107a.

## How the tables were measured

- Latency: CUPTI kernel time with cold L2, taken with FlashInfer's GPU
timer in `flashinfer.testing`. Inputs are BF16, and all times are in us.
- Table 1: the deterministic Cake kernel, the strongest non-Cake kernel
and new were measured in the same process. Each value is the median of
the per-round medians over 10 rounds.
- A/B values: the previous Cake and new (A/B) columns and all of Table 2
are medians of the pre-registered interleaved A/B, which ran 16
sequences and 160 processes. stepg_f32 has no same-process measurement,
so its deterministic Cake values also come from the A/B.
- Strongest non-Cake kernel per row: the fastest of the following, with
torch 2.14.1+cu130 and Triton 3.8.0.
  - FLA 0.6.0 `rms_norm_gated` (`fla.modules.fused_norm_gate`).
  - mamba_ssm v2.3.2 `rmsnorm_fn` (`layernorm_gated`).
- torch.compile in default and max-autotune-no-cudagraphs modes, best of
5 fresh compiles each. `#k` names the fastest compile.
- The inductor-generated persistent-reduction Triton kernel of the FP32
formula, launched directly.
- Deterministic Cake: `flashinfer.cake_rmsnorm_silu_gate_det_train`,
unchanged by this PR.
- Operations:
- `fwd` is one eager forward call, and `fwdg` is the forward replayed
from a CUDA graph.
  - `bwdg` is the backward replayed from a CUDA graph.
- `ckptg` is the checkpointed step (2 x forward + backward) in one CUDA
graph, and `stepg_f32` is the same step with an FP32 dw.
  - `fwd + bwd` is fwdg + bwdg, derived.
- In Table 2, the first five shapes run the new module. 260x48, 1031x48,
2048x48, 3533x48, 7685x48, 10600x48 and 16384x48 run the same code in
both trees.

## Cells below 1x

- vs the strongest non-Cake kernel (Table 1): none.
- vs the deterministic Cake kernel: none.
- vs the previous Cake route (A/B), only at cells that run the same code
in both trees:
  - bwdg (Table 1): 8192x32 0.9998, 7684x48 0.99999
- Table 2: 1031x48 stepg_f32 0.9997, 1031x48 fwd + bwd 0.998, 2048x48
stepg_f32 0.9996, 3533x48 ckptg 0.9996, 3533x48 stepg_f32 0.9999,
7685x48 stepg_f32 0.9999, 7685x48 fwd + bwd 0.9998, 10600x48 stepg_f32
0.99996, 16384x48 fwd + bwd 0.9999

## Results on R200 (sm_107a, 212 SMs)

- GPU: R200 (VR200 node; nvidia-smi name 'NVIDIA Graphics Device'),
sm_107a, compute capability 10.7, 212 SMs, driver 620.43.
- CUDA: 13.4 (nvcc Build cuda_13.4.r13.4/compiler.38855100_0); PyTorch
2.14.1+cu130 (CUDA 13.0); Triton 3.8.0; Python 3.14.8.

### Table 1 (R200, sm_107a, CUDA 13.4): new vs the deterministic Cake
kernel, the strongest non-Cake kernel and the previous Cake route

| T x H | op | det Cake us | strongest non-Cake us | strongest non-Cake
kernel | new us | previous Cake us (A/B) | new us (A/B) | det / new |
non-Cake / new | previous / new (A/B) |
|---|---|---|---|---|---|---|---|---|---|---|
| 3534x48 | fwd | 18.192 | 17.408 | torch.compile default #1 | 16.256 |
18.272 | 16.241 | 1.119 | 1.071 | 1.125 |
| 3534x48 | fwdg | 18.256 | 16.896 | torch.compile default flashinfer-ai#3 | 16.144 |
18.088 | 16.096 | 1.131 | 1.047 | 1.124 |
| 3534x48 | bwdg | 38.528 | 37.072 | FLA rms_norm_gated | 33.136 |
33.088 | 33.088 | 1.163 | 1.119 | 1.00001 |
| 3534x48 | ckptg | 72.831 | 68.273 | FLA rms_norm_gated | 63.264 |
66.264 | 63.048 | 1.151 | 1.079 | 1.051 |
| 3534x48 | stepg_f32 | 72.576 (A/B) | not measured | - | - | 66.392 |
63.392 | 1.145 (A/B) | n/a | 1.047 |
| 4097x48 | fwd | 20.416 | 19.328 | FLA rms_norm_gated | 17.889 | 19.904
| 17.888 | 1.141 | 1.080 | 1.113 |
| 4097x48 | fwdg | 20.192 | 19.104 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#2 | 17.825 | 19.872 | 17.880 | 1.133 | 1.072
| 1.111 |
| 4097x48 | bwdg | 40.064 | 40.689 | FLA rms_norm_gated | 37.057 |
37.128 | 37.120 | 1.081 | 1.098 | 1.0002 |
| 4097x48 | ckptg | 78.544 | 75.376 | FLA rms_norm_gated | 70.464 |
73.808 | 70.536 | 1.115 | 1.070 | 1.046 |
| 4097x48 | stepg_f32 | 78.440 (A/B) | not measured | - | - | 73.816 |
70.849 | 1.107 (A/B) | n/a | 1.042 |
| 8192x32 | fwd | 26.304 | 24.928 | FLA rms_norm_gated | 23.072 | 25.961
| 22.944 | 1.140 | 1.080 | 1.131 |
| 8192x32 | fwdg | 26.272 | 24.784 | FLA rms_norm_gated | 23.009 |
25.961 | 22.928 | 1.142 | 1.077 | 1.132 |
| 8192x32 | bwdg | 50.352 | 50.608 | FLA rms_norm_gated | 46.048 |
45.992 | 46.000 | 1.093 | 1.099 | 0.9998 |
| 8192x32 | ckptg | 100.273 | 96.256 | FLA rms_norm_gated | 89.616 |
94.256 | 89.256 | 1.119 | 1.074 | 1.056 |
| 8192x32 | stepg_f32 | 99.885 (A/B) | not measured | - | - | 94.256 |
89.425 | 1.117 (A/B) | n/a | 1.054 |
| 6000x48 | fwd | 28.096 | 26.624 | torch.compile default #1 | 24.673 |
28.064 | 24.704 | 1.139 | 1.079 | 1.136 |
| 6000x48 | fwdg | 28.048 | 26.417 | torch.compile default flashinfer-ai#3 | 24.640 |
27.872 | 24.544 | 1.138 | 1.072 | 1.136 |
| 6000x48 | bwdg | 54.928 | 54.529 | FLA rms_norm_gated | 49.328 |
49.184 | 49.184 | 1.114 | 1.105 | 1.000003 |
| 6000x48 | ckptg | 108.096 | 103.552 | FLA rms_norm_gated | 95.904 |
101.608 | 95.824 | 1.127 | 1.080 | 1.060 |
| 6000x48 | stepg_f32 | 108.769 (A/B) | not measured | - | - | 101.760 |
95.945 | 1.134 (A/B) | n/a | 1.061 |
| 7684x48 | fwd | 35.008 | 33.168 | FLA rms_norm_gated | 30.720 | 34.712
| 30.816 | 1.140 | 1.080 | 1.126 |
| 7684x48 | fwdg | 35.008 | 32.961 | torch.compile default flashinfer-ai#5 | 30.688 |
34.537 | 30.656 | 1.141 | 1.074 | 1.127 |
| 7684x48 | bwdg | 66.208 | 65.648 | FLA rms_norm_gated | 59.824 |
59.720 | 59.720 | 1.107 | 1.097 | 0.99999 |
| 7684x48 | ckptg | 133.120 | 128.496 | FLA rms_norm_gated | 118.560 |
125.296 | 118.361 | 1.123 | 1.084 | 1.059 |
| 7684x48 | stepg_f32 | 132.496 (A/B) | not measured | - | - | 125.569 |
118.705 | 1.116 (A/B) | n/a | 1.058 |

### Table 2 (R200, sm_107a, CUDA 13.4): full step, previous Cake route
vs new (A/B medians)

| T x H | rows | op | previous Cake us | new us | previous / new | det
Cake us | det / new |
|---|---|---|---|---|---|---|---|
| 3534x48 | 169632 | ckptg | 66.264 | 63.048 | 1.051 | 72.609 | 1.152 |
| 3534x48 | 169632 | stepg_f32 | 66.392 | 63.392 | 1.047 | 72.576 |
1.145 |
| 3534x48 | 169632 | fwd + bwd | 51.176 | 49.184 | 1.041 | 56.833 |
1.156 |
| 4097x48 | 196656 | ckptg | 73.808 | 70.536 | 1.046 | 78.449 | 1.112 |
| 4097x48 | 196656 | stepg_f32 | 73.816 | 70.849 | 1.042 | 78.440 |
1.107 |
| 4097x48 | 196656 | fwd + bwd | 57.000 | 55.000 | 1.036 | 60.368 |
1.098 |
| 8192x32 | 262144 | ckptg | 94.256 | 89.256 | 1.056 | 100.032 | 1.121 |
| 8192x32 | 262144 | stepg_f32 | 94.256 | 89.425 | 1.054 | 99.885 |
1.117 |
| 8192x32 | 262144 | fwd + bwd | 71.953 | 68.929 | 1.044 | 76.656 |
1.112 |
| 6000x48 | 288000 | ckptg | 101.608 | 95.824 | 1.060 | 108.872 | 1.136
|
| 6000x48 | 288000 | stepg_f32 | 101.760 | 95.945 | 1.061 | 108.769 |
1.134 |
| 6000x48 | 288000 | fwd + bwd | 77.056 | 73.728 | 1.045 | 83.328 |
1.130 |
| 7684x48 | 368832 | ckptg | 125.296 | 118.361 | 1.059 | 132.564 | 1.120
|
| 7684x48 | 368832 | stepg_f32 | 125.569 | 118.705 | 1.058 | 132.496 |
1.116 |
| 7684x48 | 368832 | fwd + bwd | 94.257 | 90.376 | 1.043 | 100.800 |
1.115 |
| 260x48 | 12480 | ckptg | 14.704 | 14.704 | 1.000 | 18.064 | 1.229 |
| 260x48 | 12480 | stepg_f32 | 14.352 | 14.344 | 1.001 | 17.472 | 1.218
|
| 260x48 | 12480 | fwd + bwd | 12.664 | 12.664 | 1.00002 | 15.160 |
1.197 |
| 1031x48 | 49488 | ckptg | 26.592 | 26.584 | 1.0003 | 29.768 | 1.120 |
| 1031x48 | 49488 | stepg_f32 | 26.624 | 26.632 | 0.9997 | 29.656 |
1.114 |
| 1031x48 | 49488 | fwd + bwd | 22.224 | 22.272 | 0.998 | 26.624 | 1.195
|
| 2048x48 | 98304 | ckptg | 43.328 | 43.328 | 1.000 | 46.537 | 1.074 |
| 2048x48 | 98304 | stepg_f32 | 42.832 | 42.848 | 0.9996 | 45.896 |
1.071 |
| 2048x48 | 98304 | fwd + bwd | 33.952 | 33.952 | 1.00001 | 37.968 |
1.118 |
| 3533x48 | 169584 | ckptg | 67.192 | 67.216 | 0.9996 | 72.520 | 1.079 |
| 3533x48 | 169584 | stepg_f32 | 67.152 | 67.156 | 0.9999 | 72.496 |
1.080 |
| 3533x48 | 169584 | fwd + bwd | 51.280 | 51.272 | 1.0002 | 56.736 |
1.107 |
| 7685x48 | 368880 | ckptg | 121.057 | 121.009 | 1.0004 | 132.776 |
1.097 |
| 7685x48 | 368880 | stepg_f32 | 121.136 | 121.152 | 0.9999 | 132.832 |
1.096 |
| 7685x48 | 368880 | fwd + bwd | 92.017 | 92.032 | 0.9998 | 100.688 |
1.094 |
| 10600x48 | 508800 | ckptg | 162.752 | 162.692 | 1.0004 | 173.993 |
1.069 |
| 10600x48 | 508800 | stepg_f32 | 162.858 | 162.865 | 0.99996 | 173.985
| 1.068 |
| 10600x48 | 508800 | fwd + bwd | 123.296 | 123.280 | 1.0001 | 131.025 |
1.063 |
| 16384x48 | 786432 | ckptg | 236.545 | 236.453 | 1.0004 | 254.433 |
1.076 |
| 16384x48 | 786432 | stepg_f32 | 236.737 | 236.643 | 1.0004 | 254.441 |
1.075 |
| 16384x48 | 786432 | fwd + bwd | 177.737 | 177.761 | 0.9999 | 188.721 |
1.062 |


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

<!-- coderabbit-ai-generated:v1 -->

## Summary by CodeRabbit

* **Performance**
* Updated RMSNorm-SiLU-gate training execution for newer GPU
architectures, including sm_107a. The revised path supports a lower
minimum workload threshold on that architecture and applies bulk L2
prefetching across supported architectures.
* **Documentation**
  * Clarified the description of mid-forward L2 prefetching.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Yingyi Huang <averyh@nvidia.com>
ruoqianguo pushed a commit that referenced this pull request Nov 5, 2026
… on SM103 (flashinfer-ai#8673)

This PR adds an extra-long forward tier on sm_103a to the
non-deterministic package of Cake's SiLU-gated RMSNorm training kernel
(`flashinfer.cake_rmsnorm_silu_gate_train` with `deterministic=False`).
From 3000 rows per SM, the sm_103a forward now runs
`cake_rmsnorm_silu_gate_train_7f014401d5cc855ab883`, and this route is
tried before the long forward's. The new module is a 256-thread forward
with the packed gate. In it, thread 0 also warms the CTA's next row
block in L2, the same way the mid forward warms its later blocks: one
bulk prefetch per tensor wherever the inputs x and z hold their rows
packed. All nine changed shapes in Table 1 are at or above 3000 rows per
SM on the 152-SM GB300.

The previous Cake baseline below is the long forward,
`cake_rmsnorm_silu_gate_train_7b7fac905aff1ddaa258`. It ran these inputs
before this PR, and it still runs sm_103a inputs from 2400 up to 3000
rows per SM. This PR removes no module. Every other module and route
runs the same code as before, including the backward, the short, mid and
long forwards, and every sm_100a and sm_107a route.

The PR is one commit on FlashInfer main after PR flashinfer-ai#8656. The A/B compared
two FlashInfer trees. In the first, there is no extra-long route, so the
long forward also serves 3000 rows per SM and up. The second is the same
tree plus this PR's sm_103a route. Both trees predate PR flashinfer-ai#8656, which
changed only the sm_107a mid forward. In the measured tree, the new
module's sources are byte-identical to this PR's.

A speedup is baseline us / new us, so a value above 1 means this PR is
faster. The table gives ranges (min-max) over the nine changed shapes of
Table 1 on GB300 (sm_103a, 152 SMs), CUDA 13.4.

| op | det Cake / new | strongest non-Cake / new | previous Cake / new
(A/B) |
|---|---|---|---|
| fwd | 1.134-1.164 | 1.061-1.133 | 1.039-1.050 |
| fwdg | 1.134-1.165 | 1.053-1.134 | 1.039-1.049 |
| bwdg | 1.114-1.147 | 1.091-1.115 | 0.9999-1.0002 |
| ckptg | 1.123-1.144 | 1.093-1.121 | 1.017-1.022 |
| stepg_f32 | 1.125-1.145 (A/B) | - | 1.017-1.021 |
| fwd + bwd | 1.129-1.143 (A/B) | - | 1.014-1.018 |

In the pre-registered A/B, the code changes in 36 cells (fwd, fwdg,
ckptg and stepg_f32 at the nine shapes), and new is faster than the
previous Cake route in all 36. bwdg and bwdg_f32 run the same code in
both trees. Neither the strongest non-Cake kernel (Table 1) nor the
deterministic Cake kernel (Tables 1 and 2) is faster than new on any
row. Every cell below 1x is a same-code cell against the previous Cake
route and is within 0.1 % of parity. "Cells below 1x" lists each one.

The kernel's other Cake variants are the deterministic package
`flashinfer.cake_rmsnorm_silu_gate_det_train` (the same API with
`deterministic=True`) and the FP32 weight-gradient output of the
non-deterministic package; both packages ship on sm_100a, sm_103a and
sm_107a, and this PR changes only the non-deterministic package's
forward on sm_103a from 3000 rows per SM.

## How the tables were measured

- Latency: CUPTI kernel time with cold L2, taken with FlashInfer's GPU
timer in `flashinfer.testing`. Inputs are BF16, and all times are in us.
- Table 1: the deterministic Cake kernel, the strongest non-Cake kernel
and new were measured in the same process. Each value is the median of
the per-round medians over 10 rounds.
- A/B values: the previous Cake and new (A/B) columns and all of Table 2
are medians of the pre-registered interleaved A/B, which ran 16
sequences and 160 processes. stepg_f32 has no same-process measurement,
so its deterministic Cake values also come from the A/B.
- Strongest non-Cake kernel per row: the fastest of the following, with
torch 2.14.1+cu130 and Triton 3.8.0.
  - FLA 0.6.0 `rms_norm_gated` (`fla.modules.fused_norm_gate`).
  - mamba_ssm v2.3.2 `rmsnorm_fn` (`layernorm_gated`).
- torch.compile in default and max-autotune-no-cudagraphs modes, best of
5 fresh compiles each. `#k` names the fastest compile.
- The inductor-generated persistent-reduction Triton kernel of the FP32
formula, launched directly.
- Deterministic Cake: `flashinfer.cake_rmsnorm_silu_gate_det_train`,
unchanged by this PR.
- Operations:
- `fwd` is one eager forward call, and `fwdg` is the forward replayed
from a CUDA graph.
- `bwdg` is the backward replayed from a CUDA graph, and `bwdg_f32` is
the same backward with an FP32 dw.
- `ckptg` is the checkpointed step (2 x forward + backward) in one CUDA
graph, and `stepg_f32` is the same step with an FP32 dw.
  - `fwd + bwd` is fwdg + bwdg, derived.
- In Table 2, the forward at the first nine shapes runs the new module.
7600x48, 9120x48 and 9499x48 are below 3000 rows per SM and run the same
code in both trees.

## Cells below 1x

- vs the strongest non-Cake kernel (Table 1): none.
- vs the deterministic Cake kernel (Tables 1 and 2): none.
- vs the previous Cake route (A/B), only at cells that run the same code
in both trees:
  - Table 1, bwdg: 9500x48 0.99996, 9975x48 0.9999
- Table 2, changed shapes (backward cells): 9500x48 bwdg 0.99996,
9975x48 bwdg 0.9999, 9975x48 bwdg_f32 0.9998, 19000x48 bwdg_f32 0.99996
- Table 2, same-code shapes: 7600x48 fwd 0.9999, 7600x48 ckptg 0.9995,
7600x48 bwdg_f32 0.9998, 7600x48 stepg_f32 0.9998, 9120x48 fwd 0.9999,
9120x48 ckptg 0.99996, 9120x48 stepg_f32 0.9998, 9499x48 fwdg 0.99999,
9499x48 bwdg_f32 0.9999
- The same-process run behind Table 1 also timed the previous Cake
route. Those times are not in the tables. Its bwdg previous / new, where
both routes run the same backward module, is below 1 at 9975x48 0.9997
(107.361 / 107.392 us), 11400x48 0.999 (118.688 / 118.752 us), 14250x48
0.9998 (146.497 / 146.529 us), 19000x48 0.999 (189.217 / 189.312 us) and
32737x48 0.9999 (316.057 / 316.097 us).

## Results on GB300 (sm_103a, 152 SMs)

- GPU: NVIDIA GB300, sm_103a, compute capability 10.3, 152 SMs, driver
580.159.03.
- CUDA: 13.4 (nvcc Build cuda_13.4.r13.4/compiler.38855100_0); PyTorch
2.14.1+cu130 (CUDA 13.0); Triton 3.8.0; Python 3.14.8.

### Table 1 (GB300, sm_103a, CUDA 13.4): new vs the deterministic Cake
kernel, the strongest non-Cake kernel and the previous Cake route

| T x H | op | det Cake us | strongest non-Cake us | strongest non-Cake
kernel | new us | previous Cake us (A/B) | new us (A/B) | det / new |
non-Cake / new | previous / new (A/B) |
|---|---|---|---|---|---|---|---|---|---|---|
| 9500x48 | fwd | 63.937 | 59.712 | torch.compile
max-autotune-no-cudagraphs #1 | 56.256 | 59.088 | 56.592 | 1.137 | 1.061
| 1.044 |
| 9500x48 | fwdg | 64.001 | 59.328 | torch.compile
max-autotune-no-cudagraphs #1 | 56.320 | 59.177 | 56.608 | 1.136 | 1.053
| 1.045 |
| 9500x48 | bwdg | 116.144 | 111.921 | FLA rms_norm_gated | 101.873 |
102.476 | 102.481 | 1.140 | 1.099 | 0.99996 |
| 9500x48 | ckptg | 238.009 | 231.377 | FLA rms_norm_gated | 211.617 |
215.305 | 211.424 | 1.125 | 1.093 | 1.018 |
| 9500x48 | stepg_f32 | 239.080 (A/B) | not measured | - | - | 215.240 |
211.644 | 1.130 (A/B) | n/a | 1.017 |
| 9975x48 | fwd | 68.000 | 63.856 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#2 | 59.008 | 61.489 | 58.817 | 1.152 | 1.082
| 1.045 |
| 9975x48 | fwdg | 68.216 | 63.840 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#2 | 59.145 | 61.569 | 58.964 | 1.153 | 1.079
| 1.044 |
| 9975x48 | bwdg | 121.408 | 117.809 | FLA rms_norm_gated | 107.392 |
107.409 | 107.417 | 1.131 | 1.097 | 0.9999 |
| 9975x48 | ckptg | 250.129 | 242.209 | FLA rms_norm_gated | 221.313 |
225.312 | 221.624 | 1.130 | 1.094 | 1.017 |
| 9975x48 | stepg_f32 | 249.065 (A/B) | not measured | - | - | 224.568 |
220.272 | 1.131 (A/B) | n/a | 1.020 |
| 10450x48 | fwd | 69.600 | 65.872 | torch.compile default flashinfer-ai#4 | 61.184 |
63.804 | 61.064 | 1.138 | 1.077 | 1.045 |
| 10450x48 | fwdg | 69.696 | 66.272 | torch.compile default flashinfer-ai#4 | 61.408
| 63.873 | 61.232 | 1.135 | 1.079 | 1.043 |
| 10450x48 | bwdg | 126.016 | 122.081 | FLA rms_norm_gated | 110.880 |
111.280 | 111.264 | 1.137 | 1.101 | 1.0001 |
| 10450x48 | ckptg | 259.129 | 253.009 | FLA rms_norm_gated | 230.737 |
234.784 | 230.616 | 1.123 | 1.097 | 1.018 |
| 10450x48 | stepg_f32 | 260.468 (A/B) | not measured | - | - | 235.060
| 231.064 | 1.127 (A/B) | n/a | 1.017 |
| 11400x48 | fwd | 75.841 | 71.649 | torch.compile default #1 | 66.624 |
69.601 | 66.608 | 1.138 | 1.075 | 1.045 |
| 11400x48 | fwdg | 75.873 | 72.097 | torch.compile default #1 | 66.736
| 69.712 | 66.840 | 1.137 | 1.080 | 1.043 |
| 11400x48 | bwdg | 136.161 | 132.464 | FLA rms_norm_gated | 118.752 |
118.656 | 118.656 | 1.147 | 1.115 | 1.000 |
| 11400x48 | ckptg | 281.393 | 274.785 | FLA rms_norm_gated | 247.633 |
252.912 | 247.816 | 1.136 | 1.110 | 1.021 |
| 11400x48 | stepg_f32 | 281.760 (A/B) | not measured | - | - | 252.896
| 247.976 | 1.136 (A/B) | n/a | 1.020 |
| 14250x48 | fwd | 93.856 | 87.329 | torch.compile
max-autotune-no-cudagraphs #1 | 80.624 | 84.385 | 80.384 | 1.164 | 1.083
| 1.050 |
| 14250x48 | fwdg | 94.000 | 87.889 | torch.compile
max-autotune-no-cudagraphs #1 | 80.704 | 84.481 | 80.496 | 1.165 | 1.089
| 1.049 |
| 14250x48 | bwdg | 166.017 | 161.336 | FLA rms_norm_gated | 146.529 |
146.320 | 146.320 | 1.133 | 1.101 | 1.000 |
| 14250x48 | ckptg | 346.897 | 337.257 | FLA rms_norm_gated | 303.441 |
309.408 | 303.016 | 1.143 | 1.111 | 1.021 |
| 14250x48 | stepg_f32 | 345.600 (A/B) | not measured | - | - | 309.401
| 303.148 | 1.140 (A/B) | n/a | 1.021 |
| 16384x48 | fwd | 106.257 | 103.825 | FLA rms_norm_gated | 91.617 |
95.752 | 91.384 | 1.160 | 1.133 | 1.048 |
| 16384x48 | fwdg | 106.368 | 103.968 | FLA rms_norm_gated | 91.713 |
95.849 | 91.488 | 1.160 | 1.134 | 1.048 |
| 16384x48 | bwdg | 184.561 | 181.889 | FLA rms_norm_gated | 165.473 |
165.861 | 165.853 | 1.115 | 1.099 | 1.00005 |
| 16384x48 | ckptg | 390.258 | 383.401 | FLA rms_norm_gated | 344.001 |
350.948 | 343.357 | 1.134 | 1.115 | 1.022 |
| 16384x48 | stepg_f32 | 391.796 (A/B) | not measured | - | - | 350.737
| 343.433 | 1.141 (A/B) | n/a | 1.021 |
| 19000x48 | fwd | 122.529 | 114.848 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#2 | 105.600 | 110.257 | 105.569 | 1.160 |
1.088 | 1.044 |
| 19000x48 | fwdg | 122.577 | 114.689 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#2 | 105.632 | 110.400 | 105.689 | 1.160 |
1.086 | 1.045 |
| 19000x48 | bwdg | 214.337 | 209.449 | FLA rms_norm_gated | 189.312 |
189.176 | 189.144 | 1.132 | 1.106 | 1.0002 |
| 19000x48 | ckptg | 453.474 | 440.353 | FLA rms_norm_gated | 396.322 |
404.440 | 396.276 | 1.144 | 1.111 | 1.021 |
| 19000x48 | stepg_f32 | 452.042 (A/B) | not measured | - | - | 404.200
| 396.216 | 1.141 (A/B) | n/a | 1.020 |
| 32737x48 | fwd | 205.408 | 192.161 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#5 | 176.511 | 183.425 | 176.529 | 1.164 |
1.089 | 1.039 |
| 32737x48 | fwdg | 205.441 | 192.217 | torch.compile
max-autotune-no-cudagraphs flashinfer-ai#3 | 176.544 | 183.601 | 176.656 | 1.164 |
1.089 | 1.039 |
| 32737x48 | bwdg | 354.705 | 348.737 | FLA rms_norm_gated | 316.097 |
316.376 | 316.360 | 1.122 | 1.103 | 1.0001 |
| 32737x48 | ckptg | 759.283 | 743.979 | FLA rms_norm_gated | 663.666 |
677.643 | 664.382 | 1.144 | 1.121 | 1.020 |
| 32737x48 | stepg_f32 | 760.154 (A/B) | not measured | - | - | 677.238
| 663.723 | 1.145 (A/B) | n/a | 1.020 |
| 16384x32 | fwd | 73.216 | 70.288 | torch.compile
max-autotune-no-cudagraphs #1 | 64.544 | 65.601 | 62.816 | 1.134 | 1.089
| 1.044 |
| 16384x32 | fwdg | 73.312 | 70.416 | torch.compile
max-autotune-no-cudagraphs #1 | 64.656 | 65.660 | 62.888 | 1.134 | 1.089
| 1.044 |
| 16384x32 | bwdg | 128.641 | 125.937 | FLA rms_norm_gated | 115.424 |
115.448 | 115.441 | 1.114 | 1.091 | 1.0001 |
| 16384x32 | ckptg | 268.505 | 262.737 | FLA rms_norm_gated | 238.816 |
242.144 | 238.000 | 1.124 | 1.100 | 1.017 |
| 16384x32 | stepg_f32 | 267.669 (A/B) | not measured | - | - | 242.037
| 237.872 | 1.125 (A/B) | n/a | 1.018 |

### Table 2 (GB300, sm_103a, CUDA 13.4): full step, previous Cake route
vs new (A/B medians)

| T x H | rows | op | previous Cake us | new us | previous / new | det
Cake us | det / new |
|---|---|---|---|---|---|---|---|
| 9500x48 | 456000 | fwd | 59.088 | 56.592 | 1.044 | 64.288 | 1.136 |
| 9500x48 | 456000 | fwdg | 59.177 | 56.608 | 1.045 | 64.416 | 1.138 |
| 9500x48 | 456000 | bwdg | 102.476 | 102.481 | 0.99996 | 116.784 |
1.140 |
| 9500x48 | 456000 | ckptg | 215.305 | 211.424 | 1.018 | 239.224 | 1.131
|
| 9500x48 | 456000 | bwdg_f32 | 102.444 | 102.433 | 1.0001 | 116.888 |
1.141 |
| 9500x48 | 456000 | stepg_f32 | 215.240 | 211.644 | 1.017 | 239.080 |
1.130 |
| 9500x48 | 456000 | fwd + bwd | 161.653 | 159.089 | 1.016 | 181.200 |
1.139 |
| 9975x48 | 478800 | fwd | 61.489 | 58.817 | 1.045 | 67.008 | 1.139 |
| 9975x48 | 478800 | fwdg | 61.569 | 58.964 | 1.044 | 67.072 | 1.138 |
| 9975x48 | 478800 | bwdg | 107.409 | 107.417 | 0.9999 | 121.312 | 1.129
|
| 9975x48 | 478800 | ckptg | 225.312 | 221.624 | 1.017 | 248.973 | 1.123
|
| 9975x48 | 478800 | bwdg_f32 | 107.380 | 107.400 | 0.9998 | 121.337 |
1.130 |
| 9975x48 | 478800 | stepg_f32 | 224.568 | 220.272 | 1.020 | 249.065 |
1.131 |
| 9975x48 | 478800 | fwd + bwd | 168.977 | 166.381 | 1.016 | 188.385 |
1.132 |
| 10450x48 | 501600 | fwd | 63.804 | 61.064 | 1.045 | 70.304 | 1.151 |
| 10450x48 | 501600 | fwdg | 63.873 | 61.232 | 1.043 | 70.368 | 1.149 |
| 10450x48 | 501600 | bwdg | 111.280 | 111.264 | 1.0001 | 126.480 |
1.137 |
| 10450x48 | 501600 | ckptg | 234.784 | 230.616 | 1.018 | 260.496 |
1.130 |
| 10450x48 | 501600 | bwdg_f32 | 111.216 | 111.208 | 1.0001 | 126.400 |
1.137 |
| 10450x48 | 501600 | stepg_f32 | 235.060 | 231.064 | 1.017 | 260.468 |
1.127 |
| 10450x48 | 501600 | fwd + bwd | 175.153 | 172.496 | 1.015 | 196.848 |
1.141 |
| 16384x32 | 524288 | fwd | 65.601 | 62.816 | 1.044 | 72.704 | 1.157 |
| 16384x32 | 524288 | fwdg | 65.660 | 62.888 | 1.044 | 72.769 | 1.157 |
| 16384x32 | 524288 | bwdg | 115.448 | 115.441 | 1.0001 | 128.564 |
1.114 |
| 16384x32 | 524288 | ckptg | 242.144 | 238.000 | 1.017 | 267.521 |
1.124 |
| 16384x32 | 524288 | bwdg_f32 | 115.468 | 115.464 | 1.00003 | 128.392 |
1.112 |
| 16384x32 | 524288 | stepg_f32 | 242.037 | 237.872 | 1.018 | 267.669 |
1.125 |
| 16384x32 | 524288 | fwd + bwd | 181.108 | 178.329 | 1.016 | 201.333 |
1.129 |
| 11400x48 | 547200 | fwd | 69.601 | 66.608 | 1.045 | 75.904 | 1.140 |
| 11400x48 | 547200 | fwdg | 69.712 | 66.840 | 1.043 | 75.976 | 1.137 |
| 11400x48 | 547200 | bwdg | 118.656 | 118.656 | 1.000 | 136.092 | 1.147
|
| 11400x48 | 547200 | ckptg | 252.912 | 247.816 | 1.021 | 281.797 |
1.137 |
| 11400x48 | 547200 | bwdg_f32 | 118.672 | 118.672 | 1.00001 | 136.136 |
1.147 |
| 11400x48 | 547200 | stepg_f32 | 252.896 | 247.976 | 1.020 | 281.760 |
1.136 |
| 11400x48 | 547200 | fwd + bwd | 188.369 | 185.496 | 1.015 | 212.068 |
1.143 |
| 14250x48 | 684000 | fwd | 84.385 | 80.384 | 1.050 | 93.344 | 1.161 |
| 14250x48 | 684000 | fwdg | 84.481 | 80.496 | 1.049 | 93.472 | 1.161 |
| 14250x48 | 684000 | bwdg | 146.320 | 146.320 | 1.000 | 165.857 | 1.134
|
| 14250x48 | 684000 | ckptg | 309.408 | 303.016 | 1.021 | 345.804 |
1.141 |
| 14250x48 | 684000 | bwdg_f32 | 146.176 | 146.168 | 1.0001 | 165.848 |
1.135 |
| 14250x48 | 684000 | stepg_f32 | 309.401 | 303.148 | 1.021 | 345.600 |
1.140 |
| 14250x48 | 684000 | fwd + bwd | 230.801 | 226.816 | 1.018 | 259.329 |
1.143 |
| 16384x48 | 786432 | fwd | 95.752 | 91.384 | 1.048 | 106.769 | 1.168 |
| 16384x48 | 786432 | fwdg | 95.849 | 91.488 | 1.048 | 106.904 | 1.169 |
| 16384x48 | 786432 | bwdg | 165.861 | 165.853 | 1.00005 | 184.792 |
1.114 |
| 16384x48 | 786432 | ckptg | 350.948 | 343.357 | 1.022 | 391.417 |
1.140 |
| 16384x48 | 786432 | bwdg_f32 | 165.744 | 165.721 | 1.0001 | 184.824 |
1.115 |
| 16384x48 | 786432 | stepg_f32 | 350.737 | 343.433 | 1.021 | 391.796 |
1.141 |
| 16384x48 | 786432 | fwd + bwd | 261.709 | 257.341 | 1.017 | 291.696 |
1.134 |
| 19000x48 | 912000 | fwd | 110.257 | 105.569 | 1.044 | 121.984 | 1.156
|
| 19000x48 | 912000 | fwdg | 110.400 | 105.689 | 1.045 | 122.048 | 1.155
|
| 19000x48 | 912000 | bwdg | 189.176 | 189.144 | 1.0002 | 214.192 |
1.132 |
| 19000x48 | 912000 | ckptg | 404.440 | 396.276 | 1.021 | 452.058 |
1.141 |
| 19000x48 | 912000 | bwdg_f32 | 189.128 | 189.136 | 0.99996 | 214.016 |
1.132 |
| 19000x48 | 912000 | stepg_f32 | 404.200 | 396.216 | 1.020 | 452.042 |
1.141 |
| 19000x48 | 912000 | fwd + bwd | 299.576 | 294.832 | 1.016 | 336.240 |
1.140 |
| 32737x48 | 1571376 | fwd | 183.425 | 176.529 | 1.039 | 206.593 | 1.170
|
| 32737x48 | 1571376 | fwdg | 183.601 | 176.656 | 1.039 | 206.609 |
1.170 |
| 32737x48 | 1571376 | bwdg | 316.376 | 316.360 | 1.0001 | 354.253 |
1.120 |
| 32737x48 | 1571376 | ckptg | 677.643 | 664.382 | 1.020 | 760.275 |
1.144 |
| 32737x48 | 1571376 | bwdg_f32 | 316.552 | 316.536 | 1.0001 | 354.101 |
1.119 |
| 32737x48 | 1571376 | stepg_f32 | 677.238 | 663.723 | 1.020 | 760.154 |
1.145 |
| 32737x48 | 1571376 | fwd + bwd | 499.977 | 493.017 | 1.014 | 560.862 |
1.138 |
| 7600x48 | 364800 | fwd | 48.416 | 48.421 | 0.9999 | 52.320 | 1.081 |
| 7600x48 | 364800 | fwdg | 48.448 | 48.448 | 1.000 | 52.448 | 1.083 |
| 7600x48 | 364800 | bwdg | 82.784 | 82.784 | 1.000003 | 97.112 | 1.173
|
| 7600x48 | 364800 | ckptg | 175.881 | 175.969 | 0.9995 | 195.777 |
1.113 |
| 7600x48 | 364800 | bwdg_f32 | 82.849 | 82.868 | 0.9998 | 97.148 |
1.172 |
| 7600x48 | 364800 | stepg_f32 | 175.988 | 176.024 | 0.9998 | 195.824 |
1.112 |
| 7600x48 | 364800 | fwd + bwd | 131.232 | 131.232 | 1.000002 | 149.560
| 1.140 |
| 9120x48 | 437760 | fwd | 56.528 | 56.536 | 0.9999 | 62.016 | 1.097 |
| 9120x48 | 437760 | fwdg | 56.496 | 56.496 | 1.000 | 62.208 | 1.101 |
| 9120x48 | 437760 | bwdg | 97.480 | 97.480 | 1.000003 | 112.860 | 1.158
|
| 9120x48 | 437760 | ckptg | 207.985 | 207.993 | 0.99996 | 230.096 |
1.106 |
| 9120x48 | 437760 | bwdg_f32 | 97.552 | 97.544 | 1.0001 | 112.752 |
1.156 |
| 9120x48 | 437760 | stepg_f32 | 207.868 | 207.904 | 0.9998 | 230.137 |
1.107 |
| 9120x48 | 437760 | fwd + bwd | 153.977 | 153.977 | 1.000002 | 175.067
| 1.137 |
| 9499x48 | 455952 | fwd | 59.344 | 59.320 | 1.0004 | 63.952 | 1.078 |
| 9499x48 | 455952 | fwdg | 59.424 | 59.424 | 0.99999 | 64.128 | 1.079 |
| 9499x48 | 455952 | bwdg | 102.336 | 102.320 | 1.0002 | 116.840 | 1.142
|
| 9499x48 | 455952 | ckptg | 215.769 | 215.741 | 1.0001 | 238.488 |
1.105 |
| 9499x48 | 455952 | bwdg_f32 | 102.328 | 102.336 | 0.9999 | 116.664 |
1.140 |
| 9499x48 | 455952 | stepg_f32 | 214.561 | 214.540 | 1.0001 | 238.336 |
1.111 |
| 9499x48 | 455952 | fwd + bwd | 161.760 | 161.745 | 1.0001 | 180.968 |
1.119 |


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

<!-- coderabbit-ai-generated:v1 -->

## Summary by CodeRabbit

* **New Features**
  * Added support for RMSNorm with SiLU gating in training workflows.
* On sm_103a, large inputs with at least 3,000 rows per SM now use an
extra-long forward path. This path follows the same launch-grid behavior
as the long forward path and can prefetch the next row block.
* **Bug Fixes**
* Improved handling of forward-path selection around the extra-long
threshold.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Yingyi Huang <averyh@nvidia.com>
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