Skip to content

[AMD][DSV4] route bf16->fp32 GEMM to aiter's tuned FlyDSL kernel - #41904

Closed
AMD-yanfeiwang wants to merge 1 commit into
sgl-project:mainfrom
AMD-yanfeiwang:perf/dsv4-bf16-fp32-gemm-aiter-route
Closed

AMD-yanfeiwang wants to merge 1 commit into
sgl-project:mainfrom
AMD-yanfeiwang:perf/dsv4-bf16-fp32-gemm-aiter-route

Conversation

@AMD-yanfeiwang

@AMD-yanfeiwang AMD-yanfeiwang commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

On ROCm, linear_bf16_fp32 (bf16 x bf16 -> fp32) runs torch.mm(out_dtype=fp32), i.e. hipBLASLt. For the DeepSeek-V4 compressor wkv_gate (K=7168, N=1024 HCA / N=2560 fused CSA) that takes 11-16 us per call at decode sizes (M<=32), and a DSv4-Pro decode step makes 61 of these calls. ROCm/aiter#6005 makes the FlyDSL HGEMM fp32-accurate for fp32 output and adds tuned FlyDSL rows for these shapes (6-14 us).

Modifications

  • kernels/ops/gemm/bf16_fp32.py: on ROCm, _linear_bf16_fp32_cublas looks up aiter's tuned bf16 -> fp32 config for (M, N, K). If it is a FlyDSL row, it calls aiter.tuned_gemm.tgemm.mm(x, w, otype=fp32). Otherwise it uses torch.mm(out_dtype=fp32) as before.
  • Depends on [FlyDSL] HGEMM: keep the C shuffle in fp32 for fp32 output; DSv4 wkv_gate fp32 rows ROCm/aiter#6005 for the fp32-accurate kernel and the DSv4 rows (M<=32 only; larger M stays on torch). Without it, none of the current callers' shapes has a FlyDSL fp32 row (the only ones on aiter main are N=6144, K=2048/3072), so everything stays on torch.mm. The same holds when aiter is not installed.

Accuracy Tests

Speed Tests and Profiling

Kernel, wkv_gate through linear_bf16_fp32, 1x MI355X, CUDA graph of 64 calls with 8 rotating weights, us per call:

M N=1024 torch.mm N=1024 this PR N=2560 torch.mm N=2560 this PR
1 14.28 5.80 16.43 9.33
8 14.07 6.27 11.64 10.02
16 11.32 6.65 12.34 11.16
32 11.08 7.79 16.32 14.10
48 8.98 8.97 16.14 16.03

N=1024 M=1/8 come from the aiter tuning sweep (same timing method); the other cells time the sglang route.

E2E, DeepSeek-V4-Pro fp8, TP8 MI355X, image lmsysorg/sglang-rocm:v0.5.20-rocm724-mi35x-20260927, 8k in / 1k out, step time (ms). Before = image + our DSv4 decode stack: #41383 (with ROCm/aiter#5882), #38919 + #38920 (SGLANG_OPT_DSV4_C4_COMPRESSOR_GEMM_FUSION=1), the DSpark verify ring write and the MoE small-batch sort. After = before + ROCm/aiter#6005 + this PR. Paired, 2 boots x 3 reps:

cell before after delta mean [min, max]
plain c8 12.22 11.88 -2.71% [-0.365, -0.304 ms]
plain c32 15.79 15.62 -1.07% [-0.195, -0.137 ms]
DSpark b6 c2 15.01 14.83 -1.14% [-0.200, -0.127 ms]
DSpark b6 c4 17.60 17.39 -1.17% [-0.258, -0.125 ms]

All 24 pairs are faster. DSpark c16/c64 (M>32) are unchanged by construction.

Checklist


CI States

Latest PR Test (Base): ❌ Run #36731607608
Latest PR Test (Extra): ❌ Run #36731607096
Latest PR Test (AMD ROCm 10): ❌ Run #36731607442

On ROCm, linear_bf16_fp32 looks up aiter's tuned bf16 x bf16 -> fp32 config
for (M, N, K) and calls tgemm.mm(otype=fp32) when it is a FlyDSL row;
otherwise it keeps torch.mm(out_dtype=fp32). The FlyDSL rows for the DSv4
compressor wkv_gate (N=1024/2560, K=7168, M<=32) and the fp32-accumulator
fix come from ROCm/aiter#6005; without them the route stays on torch.mm.

DSv4-Pro TP8 8k/1k, paired: plain c8 -2.7%, c32 -1.1%, DSpark c2/c4
-1.1%/-1.2%; gsm8k unchanged.
@Duyi-Wang

Copy link
Copy Markdown
Collaborator

Coverd by #41931

@Duyi-Wang Duyi-Wang closed this Oct 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants