FlyDSL decode GEMM (M=1–5) and gfx942 small-M VGPR HGEMM - #1
Conversation
Add predicated K tails and partial-column handling, use RNE output conversion, and expose named compile-time defaults. Strengthen gfx950 tests with strict assertions, sentinels, boundary shapes, and conversion checks. Co-authored-by: Cursor <cursoragent@cursor.com>
Benchmark the direct FlyDSL kernel against the fast and fallback wave split-K kernels and explicit hipBLASLt using shared inputs, strict correctness checks, warmed event timing, spread, throughput, and relative speedup. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Retire duplicate decode paths in favor of unified tuned kernels, while adding architecture-isolated AOT and production small-M tuning coverage. Co-authored-by: Cursor <cursoragent@cursor.com>
Restrict small-M support and remove superseded identities while hardening AOT and optional-backend validation around the production paths. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Move decode dispatch into the shared GEMM API, complete BF16 tuner integration, and restore the architecture-specific small-M path while retaining focused GPU correctness coverage. Co-authored-by: Cursor <cursoragent@cursor.com>
Use one tensor-derived configuration entry point and perform optional bias directly in Wave and BlockMFMA epilogues, keeping persistence parsing outside the public kernel API. Co-authored-by: Cursor <cursoragent@cursor.com>
…decode Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # aiter/aot/flydsl/gemm.py
🏷️ CI GuideRuns automatically on every PR:
Extended tests (opt-in via labels):
|
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
gfx942 cannot issue 16-byte global-to-LDS DMA, so stage A through VGPRs by architecture instead of catalog/CSV knobs. Remove unused small-M AOT, tuner, and CSV dispatch, and keep AtomicRMW split-K for persistent-bias correctness. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Pull request overview
Adds exact-shape BF16 FlyDSL decode GEMM support, small-M kernel improvements, tuning integration, AOT compilation, and runtime tests.
Changes:
- Adds Wave and BlockMFMA decode kernels and public dispatch APIs.
- Integrates decode candidates into tuning, runtime selection, AOT, and tuned configurations.
- Extends gfx942 small-M support and CI coverage.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
op_tests/flydsl_tests/test_flydsl_small_m_hgemm.py |
Adds small-M correctness tests. |
op_tests/flydsl_tests/test_flydsl_decode_gemm.py |
Adds decode kernel and graph replay tests. |
csrc/gemm_a16w16/gemm_a16w16_tune.py |
Adds decode and vLLM tuning candidates. |
aiter/utility/mp_tuner.py |
Adds timing divisors and candidate timeout handling. |
aiter/tuned_gemm.py |
Adds tuned decode dispatch. |
aiter/ops/flydsl/kernels/tensor_shim.py |
Adds optional tensor placeholders and cache controls. |
aiter/ops/flydsl/kernels/splitk_hgemm.py |
Makes kernel identities shape-specific. |
aiter/ops/flydsl/kernels/small_m_hgemm.py |
Extends small-M support to gfx942. |
aiter/ops/flydsl/kernels/gemm_decode_wave.py |
Implements Wave decode GEMM. |
aiter/ops/flydsl/kernels/gemm_decode_common.py |
Defines decode configurations and primitives. |
aiter/ops/flydsl/kernels/gemm_decode_block_mfma.py |
Implements BlockMFMA decode GEMM. |
aiter/ops/flydsl/gemm_kernels.py |
Exposes and dispatches new GEMM APIs. |
aiter/ops/flydsl/__init__.py |
Exports decode and small-M APIs. |
aiter/jit/core.py |
Makes merged-config deduplication read-only. |
aiter/configs/bf16_tuned_gemm.csv |
Adds gfx942 decode tuning rows. |
aiter/aot/flydsl/gemm.py |
Adds decode AOT parsing and compilation. |
aiter/aot/flydsl/common.py |
Supports selecting AOT operation kinds. |
.github/scripts/update_split_test_times.py |
Includes new tests in timing updates. |
.github/scripts/split_tests.sh |
Adds new tests to CI shards. |
.github/scripts/aiter_test.sh |
Runs new files through pytest. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| if _overlaps(C, A) or _overlaps(C, B): | ||
| raise ValueError("C must not overlap A or B") |
Restore bf16_tuned_gemm.csv and mp_tuner to main, keep legacy HGEMM name parsing, and make the decode diff pass Ruff 0.16.0 and Black. Co-authored-by: Cursor <cursoragent@cursor.com>
FlyDSL 0.3.1 blgp is ROCDL_MFMAPermBAttr, not i32. Co-authored-by: Cursor <cursoragent@cursor.com>
…shape. Co-authored-by: Cursor <cursoragent@cursor.com>
Limit CI to the two FlyDSL pytest files, revert unused AOT kind selection, simplify tuner vLLM/bounded compare paths, and drop extra tests. Co-authored-by: Cursor <cursoragent@cursor.com>
Pytest stays validity-only; optional timing is opt-in by running the test files directly. Co-authored-by: Cursor <cursoragent@cursor.com>
Let compile/tuner reject illegal or spilling configs. Policy checks (M/N/K, tile divisibility, LDS, arch) stay. Co-authored-by: Cursor <cursoragent@cursor.com>
… decode GEMM. Co-authored-by: Cursor <cursoragent@cursor.com>
gfx950 (MI355X) microbench — BF16 decode GEMM, N=16384 K=7168Hardware: MI355X gfx950, 1 XCD (32 CUs), HBM ~1332 GB/s · ROCm: 7.2.0 · PyTorch: 2.7.1+rocm7.2.0 · FlyDSL: 0.3.1 · aiter: Method: CUDA graph 200 launches × 5 trials, median. Python launch overhead eliminated. CK =
|
Why
Skinny decode GEMM (exact M=1–5) and tiny-K small-M GEMM on gfx942 leave a gap versus the backends the A16W16 tuner already had: hipBLASLt/
torch.mm, AITER HIP wvSpltK (tuner libtypeskinny), generic FlyDSL HGEMM, and Triton. The gap is small M (decode/skinny GEMM): hipBLASLt and generic HGEMM use large GEMM tiles/policies that are a poor fit when M is 1–5 (and, for small-M, when K is tiny). HIP wvSpltK is the existing skinny option and still loses on the measured cells. Decode wins at tiny K(1536,128)and at large K(896,7168)/(2112,7168); vocab(20480,7168)is a smaller win. Small-M wins only tiny-K(1536,128)at M=8/16 and loses at(20480,7168). These are packed-graph wall/N comparisons, not a host-launch-overhead story.This PR adds two kernel families for that gap:
(N,K)=(1536,128)at M=6–16, not a general M=6–16 winner.What this PR does
gemm_decode_bf16+ Wave/BlockMFMA configs) andflydsl_small_m_hgemm.op_tests/flydsl_tests/test_flydsl_decode_gemm.pyandtest_flydsl_small_m_hgemm.py.split_tests.sh/aiter_test.sh).(arch,M,N,K)identity. No shipping tuned-CSV changes.flydsl_decodetasks (bounded candidate policy by default). Comparison-only vLLM timing stays opt-in and is never promoted.gfx942 matched microbench (this revision)
Hardware: MI325X, gfx942, 304 CU,
HIP_VISIBLE_DEVICES=0. BF16, no bias.Method: packed same-stream HIP graph wall/N for every backend (50 launches, 7 samples, median µs). Tiny kernels also N-swept at 20/50/100 launches. This is not decode-graph vs eager-torch.
rocprofv3exclusive duration was not used (it floors near ~4 µs on this GPU). Decode numbers are the best of a few representative Wave/BlockMFMA configs, not a full autotune.torchistorch.mmwith hipBLASLt preferred.skinnyis AITER HIPwvSpltK(decode) /wv_splitk_small(small-M) fromcsrc/kernels/custom_kernels.cu(tuner libtypeskinny). vLLM was not timed.N-sweep sanity on the two sub-10 µs cells (median µs): decode M=1
(1536,128)2.09 / 1.85 / 1.77 at N=20/50/100; small-M M=8 same shape 2.18 / 1.95 / 1.87. Torch stays ~4.2–4.5 µs across the sweep.Decode (M=1 and M=4)
Wide-N M=4 vs torch is modest (1.07–1.2×). The clear decode wins are tiny-K and mid-N × large-K at M=1–4.
Small-M VGPR 16×16×64 (not a general M=6–16 winner)
Tiny-K is the island. The same VGPR 16×16×64 config loses to hipBLASLt at M=8
(20480,7168). Do not treat small-M as a default for all M=6–16 shapes.