feat: support head_dim=256 for SM90 BF16 decode - #84
Open
Carlos779988 wants to merge 1 commit into
Open
Conversation
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.
Summary
Add
head_dim=256support to the existing SM90 BF16 decode paths:This PR covers decode only; D256 prefill is not included. Refs #70.
Since each D256 K/V stage is twice as large as D128, D256 uses one pipeline stage while D128 keeps two. This keeps their staged K/V shared-memory footprints comparable. The static reducer and dynamic combine kernel now iterate over output-dimension tiles instead of assuming D128, so the same code covers both D128 and D256.
While extending the tests, I also found that dynamic decode produced NaNs for
q_len=5at both D128 and D256. The cross-warp softmax reduction handled 2/4/6/8 values per lane but not 10; this adds the missing 10-value layout.Test plan
make format-checkpytest tests/test_attention_decode_bf16.py tests/test_attention_decode_qkpertoken_perhead_vperhead_fp8.py tests/test_attention_decode_qpertoken_perhead_kvpertensor_fp8.py(582 passed)q_len=5regression caseq_len=1..3, dynamicq_len=1..5, and selected GQA 4/8, NHD/HND, and page-size 16/32/64 configurationsatol=0.016,rtol=1e-5)Performance
H20, BF16,
Hq/Hkv=16/4,head_dim=256,q_len=1, CUDA Graph, 10 warmup iterations and 100 measured iterations. The software versions are CUDA 12.8, PyTorch 2.8.0, FlashAttention 3.0.0, and FlashInfer 0.6.17. Times are in microseconds; lower is better.Kdenotes 1024 tokens.Dynamic timings include the attention and combine kernels using a prebuilt task map. Task-map construction is outside the timed region, matching the exclusion of FlashInfer planning and FA3 KV-cache conversion. HPC-Ops and FlashInfer use page size 64; FA3 uses page size 256, its minimum paged-KV block size.
The FA3 result is the best per-case configuration from 48 combinations of
num_splitsand GQA packing (432 runs across the nine cases). On these cases, dynamic is 1.07-2.17x faster than FlashInfer's tensor-core path and 2.42-3.89x faster than the best tuned FA3 result. Static remains faster for the short uniform case and the 32 x 128 + 32 x 4K mix.