Repository navigation
FlyDSL A4W4 decode GEMM for M<=16 on gfx950 - #6218
johannes-graner wants to merge 5 commits into
Conversation
A4W4 (MXFP4, per_1x32 e8m0) dense GEMM for M<=16 with optional stateless split-K reduce kernel. Valid (tile_n, k_waves) pairs are (32,2) and (64,1); requires N % tile_n == 0 and K % 64 == 0.
…e shapes Rows whose kernelName starts with flydsl_decode_ route to the FlyDSL kernel; unsupported shapes and unparsable names fall back to the asm heuristic. Adds 25 rows to the qwen38_27b model config.
… rows in CK gen_instances Split-K candidates are enumerated only with --splitK and encoded as log2(partitions), matching CK and asm.
Reuses OpKind.GEMM; expands every padded M served by a tuned row (80 jobs).
🏷️ CI GuideRuns automatically on every PR:
Extended tests (opt-in via labels):
One backend per PR: PR title tags & labels: |
Motivation
Qwen3.8-27B MXFP4 decode on MI355X runs small-M dense GEMMs through the asm
f4gemm_bf16_per1x32Fp4_BpreShuffle_32x128and_64x128kernels viagemm_a4w4. This adds a FlyDSL A4W4 (MXFP4, per_1x32 e8m0) decode GEMM that is 1.7-2.3x faster on the tuned shapes with N<=8192.Technical Details
kernels/decode_gemm_mxfp4.pyplus optional split-K reduce kernelkernels/decode_gemm_mxfp4_reduce.py, with wrapperaiter/ops/flydsl/decode_gemm_mxfp4.py. Targets M<=16 on gfx950.N % tile_n == 0,K % 64 == 0. Valid(tile_n, k_waves)pairs:(32, 2)and(64, 1).gemm_a4w4routeskernelNameprefixflydsl_decode_t16x{tile_n}x{256*k_waves}_kw{k_waves}_nb{num_buffers}_sk{split_k}to the kernel. Unsupported shapes and unparsable names fall back to the asm heuristic.model_configs/qwen38_27b_a4w4_blockscale_tuned_gemm.csv.gemm_a4w4_blockscale_tune.pygains--libtype flydsl. Split-K candidates require--splitKandsplitKis stored as log2(partitions), as for CK and asm.gen_instances.pyexcludesflydsl_*rows.decodeunderOpKind.GEMM, for every padded M served by a tuned row (80 jobs).run_perftestpath reads 2-19% higher on 20 of 25 shapes, most on short K=3072 kernels (+15-19%), because of launch overhead; graph replay reproduces the CSV values. At 3 points it picks a differentnum_buffers(7168x5120 M=16; 8192x5120 M=1 and M=16). Rows were kept because dispatch reads onlykernelName, the cold-ring method better represents decode with non-cache-resident weights, and the tuner still picks FlyDSL over asm at all ten checked points. A plain re-tune therefore yields slightly different rows.Design notes for reviewers:
s_waitcnt). Code comments state the constraint.Test Plan
op_tests/flydsl_tests/test_decode_gemm_mxfp4.py: 29 oracle-based tests; each also checks that the call reached the FlyDSL kernel, so a silent fallback to asm fails the test.op_tests/test_gemm_a4w4.py: now includes the 25 decode shapes.aiter/aot/test/test_flydsl_gemm.pyand an AOT prebuild from the shipped CSV.run_perftest, 10 warmup, 101 iters).Test Result
test_gemm_a4w4.pyerr 0 on all 94 rows; AOT test passed; AOT prebuild 80/80.test_gemm_a4w4.pyon gfx950 only (the test skips other archs).N=8192 K=5120 at M=1,2,4,8 has no asm row at the merge-base; asm there used the default heuristic.
Submission Checklist
flydsl-kernel-code-cleanup: the cleanup pass and two review rounds are addressed.