Repository navigation
perf(rocm): FA-RDNA2 D=128 prefill through the register-O GQA kernel - #34
Closed
BlivionIaG wants to merge 2 commits into
Closed
BlivionIaG wants to merge 2 commits into
BlivionIaG wants to merge 2 commits into
Conversation
D=128 prefill ran the _short kernel (below 4096 keys) or the per-head varlen/split-K kernels. _short runs the online softmax row by row in one wave while the rest of the CTA waits, keeps O in LDS (read-modify-write per tile) and needs ~45 KB of LDS per CTA. The D=256 GQA prefill kernel already has O and the softmax in registers (#28) and is the validated D=256 path. * fa_prefill_paged_varlen_gqa_kernel is templated on HEAD_DIM (128/256). D=128 keeps the same thread mapping (16 rows x 16 keys, one score per thread, 8 O dims per lane) at ~14 KB of LDS per CTA. * A HEADS_PER_CTA=1, BR_STEP=16 instantiation serves odd GQA groups and MHA, so the kernel no longer needs an even group. * RDNA_ATTN routes every prefill to it while VLLM_FA_RDNA2_GQA_MODE is "subgroup" (the default); any other value restores the previous dispatch. D=256 with an even group is unchanged (bitwise). * benchmarks/kernels/benchmark_fa_rdna2_prefill.py times gqa, short, varlen and split-K on prompts, chunks and small batches. Checked in the CPU emulation against rdna_extras: D=256 even groups bit-identical to the current kernel; D=128 (G=4/7/1) and D=256 odd groups (G=3/1) within 8.9e-4 of an fp64 reference and never worse than the _short/varlen kernels on the same inputs (56 cases: multi-sequence batches, prefix chunks, single-token and zero-length requests, windows 1/17/100, custom scale, dense and hybrid layouts); randomized schedules bit-identical. gfx1030 build: no warnings or spills, 85-87 VGPRs, the D=256 instantiation unchanged. Not yet run on gfx1030 hardware. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018dwtAVjZdFLPVRucCFXBzY
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018dwtAVjZdFLPVRucCFXBzY
2 of 4 tasks
BlivionIaG
added a commit
that referenced
this pull request
Oct 2, 2026
Ports opengfx1030/vllm-rdna PR #34 onto rdna_extras. D=128 prefill ran _short (below 4096 keys) or the per-head varlen/split-K kernels. _short serializes the online softmax in one wave, keeps O in LDS (read-modify-write per tile) and needs ~45 KB LDS/CTA. The D=256 GQA prefill kernel already has O and the softmax in registers (#28). Templating it on HEAD_DIM lets D=128 take the same path at ~14 KB LDS/CTA; a HEADS_PER_CTA=1, BR_STEP=16 instantiation covers odd GQA groups and MHA, so the kernel no longer needs an even group. RDNA_ATTN routes all prefill through it while VLLM_FA_RDNA2_GQA_MODE=subgroup (default); any other value restores the previous _short/split-K/general dispatch. D=256 even groups are unchanged. gfx1030 hardware validation (2026-10-02, 4x V620): - 72/72 FA-RDNA2 kernel tests pass on the patched build (D=128 G=4/7/1 and D=256 G=6/3, dense + interleaved layouts). - D=256 even group is bitwise identical to rdna_extras (kernel-level max_abs_diff 0.0). - Kernel A/B: D=128 gqa is 4-10x faster than _short/varlen/split-K at every shape, including chunk-behind-prefix (chunk 2k@16k 126 ms vs splitk 1341 ms); max|diff| vs gqa <= 9.8e-4. - Flash-Next (D=256, TP=4, FA-RDNA2, MTP 0/2, c=1/8, 1k/16k): 8-cell matrix shows no regression vs rdna_extras. Gates: both arms build BUILD_EXIT=0; ISA 80-93 VGPR, 0 spills, 0 scratch, wave32, all four instantiations present.
Author
|
Validated on gfx1030 (4× V620) and integrated into Results:
Summary: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
Follow-up 1 from the exploration plan in #28: the D=128 prefill kernels.
rdna_extras(74315f4), which has perf(rocm): FA-RDNA2 causal tile skipping, in-place output, parallel GQA softmax #28 and perf(rocm): FA-RDNA2 decode kernel for spec-decode verify and mixed batches #29 merged and reworked. It is independent of perf(rocm): FA-RDNA2 decode, scores on every wave and 4 barriers per tile #33 and merges cleanly with it.Problem
D=128 prefill (Qwen3/Llama-class models) ran the
_shortkernel below 4096 keys. Longer sequences used the per-head general or split-K kernels. The_shortkernel (BR=32 × BC=32, 256 threads) has three costs:ds_bpermutereductions), while the other 7 waves wait at the barrier.sOis read-modify-written every tile (rescale plus P·V accumulate).The D=256 GQA prefill kernel already fixed all three for D=256 in #28: O in registers, an in-register softmax with 16-lane shuffles, and one barrier fewer. It is the validated production D=256 path: 1.63-1.74× on unchunked prefill in #28's gfx1030 A/B.
Change
fa_prefill_paged_varlen_gqa_kernelis templated onHEAD_DIM(128/256).static_asserts hold unchanged.HEADS_PER_CTA=1, BR_STEP=16instantiation keeps 16 rows per CTA from a single head.<D, 2, 8>for even groups and<D, 1, 16>otherwise.RDNA_ATTN._forward_prefillsends every prefill to this kernel whileVLLM_FA_RDNA2_GQA_MODE=subgroup, the default.off) restores the previous dispatch (_short/ split-K / general), for A/B runs.benchmarks/kernels/benchmark_fa_rdna2_prefill.pytimesgqa,short,varlenandsplitkon prompts (512-8k), 4 × 1k, and chunks behind prefixes (1k @ 8k, 2k @ 16k). It prints the max output difference vsgqa. Every kernel is its own op, so one build covers the A/B.Not in this PR:
_short/varlen_128/splitk_128. That waits on the measurements.Not a duplicate: the only other open FA-RDNA2 PR is #33, which covers the decode kernels.
AI assistance: written with Claude Code. Per AGENTS.md, a human must review every changed line and run the GPU validation below before this leaves draft.
Test Plan
For the gfx1030 agent:
_rocm_Cand checkfa_rdna2.cufor new warnings.rdna_extras.test_prefill_gqa_multiseq[*]: D=256 G=6/3, D=128 G=4/7/1 (MHA), dense and interleaved layouts.gqa128cases intest_prefill_chunked_offsetandtest_prefill_sliding_window.test_forward_split_decode[128-*]now reaches this kernel throughforward().gqato beatshortbelow 4k keys, which is the point of this PR. The 2-4× estimate in perf(rocm): FA-RDNA2 causal tile skipping, in-place output, parallel GQA softmax #28 assumed the serial softmax is ≥50% of a_shorttile; measure it.gqaloses, most likely short chunks behind long prefixes, wheresplitkhas more CTAs. If it does lose there, route those shapes back tosplitkin_forward_prefill: amax_seqlen_k/ chunk-size rule, like e0112c5 did for split decode.max|diff|vsgqashould be around 1e-3.VLLM_FA_RDNA2_GQA_MODE=subgroupvsoff:serve_gfx1030_full.sh): spot-check that prefill TTFT is unchanged. The kernel for even groups is the same code.Test Result
Offline (done):
rdna_extrasas the baseline. The harness uses fibers with block barriers, wave32 shuffles, guard-paged buffers, and NaN-poisoned outputs and dynamic LDS. All 56 cases pass. The batches cover multi-sequence prefill, prefix chunks, single-token and zero-length requests, windows 1/17/100, custom scale, dense and hybrid layouts, and block sizes 13/16/32/784:_shortand general kernels on the same inputs. Those reach up to 1.1e-3.RdnaAttentionImpl.forwardwith reference stub kernels on 47 batches.gqaand outputs match the reference.VLLM_FA_RDNA2_GQA_MODE=offthe previous dispatch returns.rdna_extrasand with perf(rocm): FA-RDNA2 decode, scores on every wave and 4 barriers per tile #33.Re-checked on
rdna_extras74315f4 (2026-10-01). The merge is clean. The base did not touch FA-RDNA2, so the sources are byte-identical to the version validated above.Cost of the same work under the current
_shortkernel and this PR'sgqa<128, 2, 8>: 32 query rows × 2 q-heads (G=2) behind a prefix. Executed counts come from the emulator; static counts come from the gfx1030 assembly of the main KV loop._short(base)gqa, D=128 (PR)The PR trades 4× more barriers per unit of work for a 10× shorter serial shuffle chain and about 3× less LDS. Those barriers are cheap because the work between them is balanced across waves. Only measurements can say whether the trade wins on every shape (Test Plan step 3).
Scope on the current launchers: none of them serves a D=128 model; Flash-Next and the 27B are D=256. For D=256 with an even group this PR is bit-identical, so it only changes D=128 models.
On gfx1030: pending, to be filled in from the plan above.
Essential Elements of an Effective PR Description Checklist
supported_models.mdandexamplesfor a new model.🤖 Generated with Claude Code
https://claude.ai/code/session_018dwtAVjZdFLPVRucCFXBzY