Repository navigation
[HIP] gfx950 A8W4 fused_moe configs for DSv4.1 TP-sharded experts - #6125
Conversation
… experts Add tuned rows for DeepSeek-V4.1-Flash routed experts sharded across TP (model_dim 5120, per-rank inter 640 at TP4 / 1152 at TP2; target 384x6 and DSpark draft 128x3; tokens 1..32768) with MXFP8 activations on interleaved gate/up rows (A8W4), the precision the checkpoint's reference runs. The default tuner sweep (TUNE_ONLY=flydslv2) only generates the fused-fp8 stage1 + moe2_layout family. At 32-64 tokens that family loses to the heuristic's bf16-out `_gui` stage1 + non-layout stage2 by up to 1.25x, and a v2-only table raised V4.1 TP4 decode TPOT from 8.2 ms to 12.8 ms. The rows here take, per shape, the faster of a v2 sweep and a TUNE_ONLY=flydsl sweep (v1 family). Each row was then checked against the heuristic on the production fused_moe op. The 7 shapes where the tuned pick measured >3% slower there carry the heuristic's own kernel pair instead; their us is the measured op time and us1/us2/err are left empty, since the tuner never timed that pair. End to end (V4.1 TP4, DSpark-5, ISL/OSL 1024/512, conc 8): 2597 vs 2552 tok/s for the heuristic, within run-to-run spread. Also fix a build error from #5652 in topk_softmax_kernels.cu: `__shared__ alignas(64) T x[]` is rejected by ROCm 7.1.1's clang ("'alignas' attribute cannot be applied to types"), which breaks module_moe_asm and with it the MoE tuner. Use `__attribute__((aligned(64)))`, as elsewhere in csrc.
🏷️ CI GuideRuns automatically on every PR:
Extended tests (opt-in via labels):
One backend per PR: PR title tags & labels: |
Motivation
DeepSeek-V4.1-Flash's routed experts are MXFP4. Its reference implementation runs them with MXFP8 activations (A8W4). On gfx950 with separated gate/up rows, aiter picks MXFP4 activations (A4W4) for these shapes instead. That leaves the routed output ~12% off the reference and costs ~1.4pp of GSM8K at TP4.
The fix on the ATOM side is to run these layers with interleaved gate/up rows and
quant_dtype_a=fp8. However, aiter had no tuned A8W4 rows for the TP-sharded V4.1 shapes, so every call fell back to the heuristic.Changes
dsv41_fp8_{tuned,untuned}_fmoe.csv: 64 rows.How the rows were chosen:
TUNE_ONLY=flydslv2only generates fused-fp8 stage1 +moe2_layoutstage2. The heuristic's family (bf16-out_guistage1 + non-layout stage2) never becomes a candidate.TUNE_ONLY=flydsl(v1-family) sweep.fused_moecall.no tuned FlyDSL config ... kn1/kn2log), withusset to the measured op time.us1/us2/errare left empty, since the tuner never timed that pair.csrc/kernels/topk_softmax_kernels.cu: one-line build fix for #5652.__shared__ alignas(64) DTYPE s_gate[...]("'alignas' attribute cannot be applied to types").module_moe_asmand, with it, the MoE tuner.__attribute__((aligned(64))), as used elsewhere incsrc.Test Plan
test_fmoewith interleaved gate/up, FP8 activations andAITER_BF16_FP8_MOE_BOUND=0on all 64 shapes, once with this table and once with the pre-change table. Compared shape by shape.no tuned FlyDSL configwarning appears.Test Result
1. Per-shape timing (this table ÷ heuristic):
2. Fallback rows: no
no tuned FlyDSL configwarnings for the 7 rows.3. End to end: 2597 vs 2552 tok/s (heuristic), TPOT 8.39 vs 8.38 ms. Within run-to-run spread.
4. Accuracy:
Notes for reviewers
TUNE_ONLY=flydslv2will produce slower-than-heuristic A8W4 tables at decode sizes unless the v1 family is also swept.test_moe_2stage.pyimport side effect. It runstest_output_buffer_contract(torch.compile) at module level, so importing it on a box whose Inductor can't build fails before any test runs.