Repository navigation
[Config] Add Qwen3.8-27B TP1 a8w8 blockscale B-preshuffle GEMM tunings for gfx950 - #6033
Conversation
…s for gfx950 119 tuned rows for the five (N, K) widths Qwen3.8-27B (FP8, 128x128 block scales) drives at TP1 on gfx950 / cu_num=256: qkv 14336x5120, GDN in_proj_qkvz 16384x5120, gate_up 34816x5120, GDN out_proj and o_proj 5120x6144, down 5120x17408, at M in 1..16384 plus the exact decode and MTP-verify sizes 24..192. Tuned on main with --compare --update_improved --min_improvement_pct 3; the untuned CSV is the 125-shape list. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
🏷️ CI GuideRuns automatically on every PR:
Extended tests (opt-in via labels):
One backend per PR: PR title tags & labels: |
yifehuan
left a comment
There was a problem hiding this comment.
Nice work, thanks! Using power-of-two M plus the real decode/MTP sizes is exactly the right way to build these tables. Kernels all exist, no key collisions, errRatio is 0 throughout. LGTM 👍
Adds 119 tuned
a8w8_blockscale_bpreshufflerows for Qwen3.8-27B (Qwen/Qwen3.8-27B-FP8, 128x128 block-scale FP8) at TP1 on gfx950 /cu_num=256, plus the untuned shape list they were tuned from.What this adds
The rows cover the five FP8 linear shapes Qwen3.8-27B drives at TP1:
qkv_proj(24 q heads with the output gate, 4 KV heads, head_dim 256)in_proj_qkvzgate_up_projout_projand full-attentiono_projdown_projM covers 1 to 16384 in powers of two, plus 24 to 192 at the exact sizes a 48-sequence decode step and its MTP verify steps (48 x 2, 48 x 3 tokens) produce.
a8w8_blockscale_bpreshuffle_untuned_gemm_qwen38_27b.csvholds the 125 shapes.mainhas no gfx950 B-preshuffle row for any of these (N, K) pairs, so every call takes the CK default instance. The existinga8w8_blockscale_tuned_gemm_qwen38_27b.csv(#5585) is gfx942 and the non-preshuffled table.Results
Tuned and re-timed on one MI355X (gfx950, ROCm 7.2) against
main(b68b0e5), withcsrc/ck_gemm_a8w8_blockscale/gemm_a8w8_blockscale_tune.py --preshuffle --libtype all --compare --update_improved --min_improvement_pct 3. The "before" column is the tuner's pre-run of the production op onmain(the CK default instance), the "after" column its post-run with the new row.main's default by 1.05x to 2.16x. The tuner dropped the other 6 (exact-M decode sizes where no kernel beat the default by 3%).fp8gemm_bf16_blockscale_BpreShufflekernels above;down_projandout_projgain 1.6x to 1.9x at M 1 to 64.Selected rows, in µs:
mainIn vLLM. vLLM
v0.30.0selectsAiterPreshuffledFp8BlockScaledMMKernelonly for (N, K) pairs that have a row in this table, so without rows the model runs the non-preshuffled path. Same host,vllm/vllm-openai-rocm:v0.30.0with aitermain(b68b0e5) installed in place of the bundled 0.1.21.post2, one GPU per engine, this file as the only difference:main, no Qwen3.8 rowsmain+ this fileGSM8K (first 250 test problems, thinking off) with the rows: 98.0%. Engine flags:
--tensor-parallel-size 1 --max-model-len 262144 --max-num-seqs 64 --enable-prefix-caching --kv-cache-dtype fp8 --attention-backend ROCM_AITER_UNIFIED_ATTN,VLLM_ROCM_USE_AITER=1. Prefill isvllm bench serve --dataset-name random --random-input-len 8192 --random-output-len 1 --num-prompts 64 --max-concurrency 16(second of two runs). Throughput is a closed loop of 48 streams with ~2,480-token prompts and exactly 500 output tokens, 120 s window, output tokens per minute by Little's law, best of two runs.With the rows the engine log shows
Selected AiterPreshuffledFp8BlockScaledMMKernel for Fp8LinearMethodand noa8w8_blockscale_bpreshuffle ... not found tuned configline; without them it selectsAiterFp8BlockScaledMMKernel.Method and validation
main(b68b0e5) insidevllm/vllm-openai-rocm:nightly(torch 2.13, Triton 3.8) on 4 MI355X; every candidate passed the tuner'scheckAllclose(atol/rtol 0.01), and every kept row has errRatio 0.0.0.1.21.post2gave 103 rows; re-timed onmain, 32 of them no longer beat the default by 3% (mostly the ASM picks at M 64 to 256), so this PR carries themainre-tune instead.op_tests/tuning_tests/test_csv_validation.pyandop_tests/tuning_tests/test_config_shape_collision.py: 37 passed with these files in place. By hand: zero duplicate(gfx, cu_num, M, N, K)keys against the 3,485 rows in the ninea8w8_blockscale_bpreshufflesourcesmainmerges.How to reproduce
Kernel level, on an MI355X with aiter
maininstalled:The compare report (pre-run, post-run and the per-shape keep or skip decision) is written under
/tmp/aiter_compare/. End to end, the recipe'sbench/launch.sh,bench/probe.sh 16 8192 1 64andbench/tpm.sh <port> <log> 48produce the vLLM table above (bench/README.mdin the recipe linked below).Scope and caveats
maincurrently does not call the B-preshuffle block-scale GEMM for dense FP8 linears (the kernel added in [ROCm][Perf] Add bpreshuffled blockscaled fp8 GEMM vllm-project/vllm#51692 was reverted in [ROCm][Bugfix] Revert #56433 + #51692 to fix accuracy breakdown for DeepSeek-V4 vllm-project/vllm#57132; [ROCm] Select AITER FP8 blockscale B-preshuffle when the shape is tuned vllm-project/vllm#56234 re-adds it). The rows take effect with vLLMv0.30.0, with that re-land, and for any direct caller ofgemm_a8w8_blockscale_bpreshuffle.The full tuning run (recipe, harness and every measurement) is in https://github.com/OpenRelayInc/inference-recipes/tree/qwen38-27b-mi355x-recipe/qwen3.8-27b-mi355x, tracked in OpenRelayInc/OpenRelay#2469.
Submission Checklist