Repository navigation
[Config] [Tune] [gfx1250] DeepSeek-V4.1-Flash BF16 and MX32 FP8 GEMM rows (complements #7246) - #7247
Conversation
…rows Tuned on MI455X (gfx1250, cu_num 256) for the exact shapes DeepSeek-V4.1-Flash (target + MTP draft) runs under DEP4. Complements ROCm#7246: the draft lm_head (N=129280, K=5120) is left to ROCm#7246 entirely, and no key added by ROCm#7246 is repeated here. - dsv41_bf16_tuned_gemm.csv: +181 gfx1250 rows (144 FlyDSL hgemm, 37 OPUS) for target lm_head N=32320 K=5120, N=1024 (fp32 out)/512/384/128/32 K=5120, N=128 K=512 and the draft N=1 K=5376 (fp32 out). These shapes had no gfx1250 row and ran the default Triton path. Rows are inserted right after the header so they do not textually conflict with ROCm#7246's appended rows. - dsv41_a8w8_blockscale_mxscale_bpreshuffle_tuned_gemm.csv: +181 gfx1250 32x32 rows (kernelId bmm, FlyDSL mxfp8_32 wmma) at M values not covered by the existing gfx1250 rows. - dsv41_batched_gemm_a8w8_blockscale_mxscale_bpreshuffle_tuned.csv (new): 30 gfx1250 32x32 batched rows (b=8). No existing row is changed and no shape repeats across configs/ and model_configs/, with or without ROCm#7246 merged. The new gfx1250 OPUS row for (16384, 512, 5120) shares its M/N/K with a gfx950 row, so it is added to _EXPECTED_GFX_KEY_FIXES in test_opus_a16w16_policy_parity.py, like the other kid-596 entries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🏷️ CI GuideRuns automatically on every PR:
Extended tests (opt-in via labels):
One backend per PR: PR title tags & labels: |
NOT READY FOR HUMAN REVIEWPR Self-ReviewRevision Waiting for the PR author. The readiness report will appear after the self-review answers are complete for this revision. Questions to answer in the PR description
Edit the Missing or invalid answers
Shadow mode reports what would block but keeps the status successful. Set |
…rows (#7247) Tuned on MI455X (gfx1250, cu_num 256) for the exact shapes DeepSeek-V4.1-Flash (target + MTP draft) runs under DEP4. Complements #7246: the draft lm_head (N=129280, K=5120) is left to #7246 entirely, and no key added by #7246 is repeated here. - dsv41_bf16_tuned_gemm.csv: +181 gfx1250 rows (144 FlyDSL hgemm, 37 OPUS) for target lm_head N=32320 K=5120, N=1024 (fp32 out)/512/384/128/32 K=5120, N=128 K=512 and the draft N=1 K=5376 (fp32 out). These shapes had no gfx1250 row and ran the default Triton path. Rows are inserted right after the header so they do not textually conflict with #7246's appended rows. - dsv41_a8w8_blockscale_mxscale_bpreshuffle_tuned_gemm.csv: +181 gfx1250 32x32 rows (kernelId bmm, FlyDSL mxfp8_32 wmma) at M values not covered by the existing gfx1250 rows. - dsv41_batched_gemm_a8w8_blockscale_mxscale_bpreshuffle_tuned.csv (new): 30 gfx1250 32x32 batched rows (b=8). No existing row is changed and no shape repeats across configs/ and model_configs/, with or without #7246 merged. The new gfx1250 OPUS row for (16384, 512, 5120) shares its M/N/K with a gfx950 row, so it is added to _EXPECTED_GFX_KEY_FIXES in test_opus_a16w16_policy_parity.py, like the other kid-596 entries. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts, keeping both sides: - kernel_fits_shape and the mxfp8 runner K-tile check: our partial last K tile (one split, 32x32 w_scale) plus main's generic K=128 two-buffer case (#7142). - gemm_a8w8_mxfp8_bpreshuffle_tune.py: keep our gfx1250 32x32 + 128x128 tuning (a superset of #7142's 128x128-only path); merge the docstrings and take main's warning text. - test_gemm_a8w8_blockscale.py: union of the imports. - dsv41 dense mxscale table: 3-way per key; of the 27 keys both sides added, the lower-us row wins (23 ours, 4 main); every row is kept verbatim. Needed beyond the textual conflicts: - The gfx950 FlyDSL blockscale block from #5969 uses b_preshuffle (renamed here) and reports BW like the other columns. - The tuner's kernelId remap also covers gfx1250 32x32 rows ("mxfp8"); gfx1250 128x128 rows keep main's kernels_list id. - dsv41_batched (#7247) repeated 6 keys of dsv4_batched, which the runtime merge rejects; drop main's copies (ours have the lower us). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Motivation
On MI455X (gfx1250), DeepSeek-V4.1-Flash served by ATOM with DEP4 plus the MTP draft model (MLPerf Endpoints agentic, c512) runs most of its BF16 GEMMs and part of its 32x32 MXFP8 GEMMs with no gfx1250 tuned row:
w_scale_block32x32): the dense (kernelIdbmm) and batched GEMMs at the M values DEP4 decode/prefill produce fall back to the FlyDSL heuristic. The existing gfx1250 rows cover other M values.This PR adds tuned gfx1250 rows for exactly those shapes.
Relation to #7246. This PR complements #7246 (DSv4.1 BF16 OPUS rows by @amd-ruitang3). The draft lm_head (N=129280, K=5120) is intentionally excluded and left to #7246 entirely. Every other key that #7246 adds (N=384 M=4096; N=32320 M=576/768) is also dropped here, so #7246's row is the one used. The two PRs merge cleanly in either order (checked below).
Technical Details
Rows only. No code changes apart from a one-line test expectation (see below). All rows are
gfx1250,cu_num256. No existing row is modified, and no other arch is touched. Indsv41_bf16_tuned_gemm.csvthe new rows sit right after the header (not at the end of the file), so they do not textually conflict with #7246, which appends at the end.aiter/configs/model_configs/dsv41_bf16_tuned_gemm.csvaiter/configs/model_configs/dsv41_a8w8_blockscale_mxscale_bpreshuffle_tuned_gemm.csvbmm, FlyDSLflydsl_bmm_mxfp8_32_wmma_*)aiter/configs/model_configs/dsv41_batched_gemm_a8w8_blockscale_mxscale_bpreshuffle_tuned.csvop_tests/test_opus_a16w16_policy_parity.py_EXPECTED_GFX_KEY_FIXESBF16 shapes covered (N, K, out dtype : number of M values):
MX32 dense shapes (N, K): (1792, 5120), (4608, 5120), (5120, 2304), (5120, 8192), (32768, 1280). Batched: b=8, (1024, 4096).
How the rows were produced:
rocm/fw-bringup-mlperf:gfx1250-atom-20261030-dsv41. That image's aiter is based on main at 2db75fc. Since then, main changes none of the FlyDSL hgemm, OPUS a16w16, FlyDSL mxfp8_32 BMM kernels or the lookup code these rows use. FlyDSL in the image is 0.4.1.Merge and duplicate rules:
gfx, cu_num+ the untuned key columns) exist inconfigs/or anymodel_configs/*sibling of the same op, or in [Config] [Perf] Tune gfx1250 DSv4.1 BF16 LM-head and router GEMMs #7246. The runtime merge therefore neither raises nor rewrites files, before or after [Config] [Perf] Tune gfx1250 DSv4.1 BF16 LM-head and router GEMMs #7246 lands._EXPECTED_GFX_KEY_FIXESsotest_shipped_tuned_selection_diff_is_exhaustivestays exhaustive.OPUS kids: the new rows reference gfx1250 a16w16 kids 178, 525–716. The opus module's
blob_gen_cmdalready globsmodel_configs/*_bf16_tuned_gemm.csv, so these kids are built with the module. When the CSV was instead passed throughAITER_CONFIG_GEMM_BF16from outside the tree, kid 178 had to be compiled by hand.Test Plan
No-GPU checks on this branch:
AITER_CONFIGS.get_config_fileforbf16_tuned_gemm,a8w8_blockscale_mxscale_bpreshuffle_tuned_gemmandbatched_gemm_a8w8_blockscale_mxscale_bpreshuffle_tunedwith no env override. This is the real configs/ + model_configs/ merge with its duplicate check. Then check that every new row appears exactly once in the merged table with its kernelName._HGEMM_KERNEL_RE(ktail0, gfx1250, matching out dtype). MX32 names must match_BMM_MX32_KERNEL_NAME_RE.get_kernel_instance('gfx1250', 'a16w16', kid, outdtype, cu_num=256).name == kernelName, andresolve_a16w16_tuned_candidate(...)must resolve to the same kid with the stored splitK.pytest op_tests/tuning_tests/test_csv_validation.py op_tests/tuning_tests/test_config_shape_collision.py op_tests/test_opus_a16w16_policy_parity.py.git mergeof main + [Config] [Perf] Tune gfx1250 DSv4.1 BF16 LM-head and router GEMMs #7246 head (d6b8b2b) + this branch, in both orders, then steps 1 and 4 again on the result.On MI455X:
6. Kernel microbenchmarks against the production default.
7. E2E ATOM A/B on DeepSeek-V4.1-Flash: DEP4 + MTP, MLPerf Endpoints agentic, c512, 10-minute FAST runs, same machine, runs interleaved.
8. A full run with inline accuracy.
Test Result
No-GPU checks:
dsv41_bf16_tuned_gemm.csvthen has 213 gfx1250 rows (181 + 32) and 0 duplicate keys; the bf16 runtime merge passes with 1235 gfx1250 rows; the three pytest files pass (68 passed, 50 subtests passed).Microbenchmarks (us, default → tuned). Error ratio (fraction of outputs outside tolerance against a reference GEMM) is 0 for every measured row, default and tuned.
E2E A/B, same machine, interleaved (DeepSeek-V4.1-Flash, DEP4 + MTP, c512, generated tok/s/GPU over the 600 s issue window):
rocm/fw-bringup-mlperf:gfx1250-atom-20261030-dsv41.Accuracy: a full MLPerf Endpoints run with inline accuracy scored 0.5544 against a gate of 0.5236 (PASS), with 27581/27581 requests completed. A reference run without these rows scored 0.5561. That run used a different MI455X node (e15-06) with our earlier full BF16 row set (including the draft lm_head rows) together with an unrelated ATOM scheduling setting (9850 → 10255 tok/s/GPU, +4.1%, on 10-minute runs; 10263 tok/s/GPU on the full run). It did not include the MX32 rows, so MX32 inline accuracy is still pending. The MX32 rows have error ratio 0 in the microbenchmarks and passed the E2E smoke checks above.
🤖 Generated with Claude Code