Skip to content

[None][perf] Triton FP8-activation MoE for decode-sized batches on Hopper - #21250

Draft
ruocheng-nv wants to merge 1 commit into
NVIDIA:mainfrom
ruocheng-nv:perf/hopper-fp8-moe-triton-decode
Draft

ruocheng-nv wants to merge 1 commit into
NVIDIA:mainfrom
ruocheng-nv:perf/hopper-fp8-moe-triton-decode

Conversation

@ruocheng-nv

Copy link
Copy Markdown
Collaborator

Description

Split out of #20878 (GLM-5.3-Flash FP8 on Hopper) so MoE owners can review it on its own. The other changes are in
#21179 (Python) and #21178 (C++).

On SM90, FP8 block-scale MoE runs through the fp8_block_scales CUTLASS leaf (DeepgemmCudaHopperFp8BlockScalesImpl).
Its grouped DeepGEMM kernel walks every expert group on one persistent CTA per SM. At decode batch sizes most experts are
empty, so the GEMMs stay far from the bandwidth bound.

The leaf's run_moe now runs Triton FP8-activation kernels when all of these hold: a plain SwiGLU (optionally clamped by
a scalar), no expert bias, no LoRA, BF16 input, no caller-provided output buffer and at most 32 tokens per rank.
Otherwise it keeps the fused op. The Triton path consists of:

  • per-1x128 FP8 activation quantization and FP8 x FP8 GEMMs with 128x128 weight scales; the grid covers only the expert
    blocks the batch can occupy;
  • SwiGLU fused with the FP8 quantization of the FC2 input;
  • a single-program moe_align for up to 128 (token, expert) pairs, and a top-k sum kernel.

moe_align_block_size also accepts expert counts that are not a power of two. This also applies to the SM120 Triton
path.

For MoE owners

  • This leaf's id names the DeepGEMM grouped GEMM, while the small-batch path is a Triton kernel. Please say if you would
    rather have the small-batch path as its own identity.
  • The leaf serves every FP8 block-scale MoE on SM90 (e.g. DeepSeek-V3/R1 FP8), so those models also take this path at
    decode sizes. So far it has only been measured on GLM-5.3-Flash (TP4, EP1).
  • With expert parallelism, (token, expert) pairs owned by other ranks keep a clamped local expert id with zero weight,
    as in the SM120 Triton path, so they are still computed.

Performance

H200, 288 experts, top-8, hidden 4096, 512 intermediate per rank (CUDA graph), full MoE: 4 tokens 64.7 us, 1 token
28.7 us. On the grouped DeepGEMM path the FC1/FC2 GEMMs alone take 53/47 us and 43/36 us.

GLM-5.3-Flash FP8, H200 TP4, MTP3, ISL 13312 / OSL 33, concurrency 1: decode step 14.4 -> 11.7 ms, 184 -> 225.5 output
tok/s per user; GSM8K unchanged. Measured on the #20878 branch (older main); not yet re-measured on this branch.

Test Coverage

  • test_triton_fp8_block_scale.py (added to l0_h100.yml):
    • FP8-activation MoE against an FP32 reference with 1x128 FP8-rounded activations: no clamp, clamp, clamp after SiLU;
      1 to 24 tokens; a non-power-of-two expert count.
    • moe_align (single-program and multi-kernel) for non-power-of-two expert counts.

PR Checklist

  • PR description clearly explains what and why.
  • Test cases are provided for new code paths.
  • No API changes.

…pper

On SM90 the CUTLASS MoE path runs FP8 block-scale expert GEMMs through the
grouped DeepGEMM kernel: one persistent CTA per SM that walks every expert
group. At decode batch sizes most experts are empty and each SM streams its
weight tiles through a single serialized pipeline, so the GEMMs stay far
from the bandwidth bound.

For a plain SwiGLU (optionally clamped by a scalar), no expert bias, no
LoRA and at most 32 tokens per rank, the SM90 fp8_block_scales leaf
(DeepgemmCudaHopperFp8BlockScalesImpl) now runs a Triton path, and keeps
the fused op otherwise:
- per 1x128 FP8 activation quantization, and FP8 x FP8 GEMMs with 128x128
  weight scales whose grid covers only the expert blocks the batch can
  occupy;
- SwiGLU fused with the FP8 quantization of the FC2 input;
- a single-program moe_align for up to 128 (token, expert) pairs and a
  top-k sum kernel.
moe_align_block_size also accepts expert counts that are not a power of two.
Without expert parallelism the routed expert IDs are used as-is.

H200, 288 experts, top-8, hidden 4096, 512 intermediate per rank (CUDA
graph), full MoE: 4 tokens 64.7 us, 1 token 28.7 us; the FC1/FC2 GEMMs on
the grouped DeepGEMM path take 53/47 us and 43/36 us.
GLM-5.3-Flash FP8, H200 TP4, MTP-3, 13K-token prompt, concurrency 1:
decode step 14.4 -> 11.7 ms, 184 -> 225.5 output tok/s per user; GSM8K
unchanged.

Signed-off-by: Ruocheng Jia <ruochengj@nvidia.com>

This branch has not been deployed

No deployments
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