Conversation
The DSV4 prefill dispatch chain in dispatch_dsv4_single covers
topk {128, 512, 1024, 2048} but not 256, so a prefill-shaped call
(num_tokens > 64) with topk=256 has no kernel and fails with
'Unsupported sparse-MLA prefill configuration'. The shape is valid
(4 x BI, between the instantiated 128 and 512) and occurs in practice
via DeepSeek-V4-Flash-DSpark under tensor-parallel=2.
Add the FP8-lane 256 branch as proposed by @eous in flashinfer-ai#3828, plus
(16, 256) and (32, 256) prefill test configs. All 44 prefill-dsv4
combos pass on GB10 (sm_121a) JIT-built from this branch; the decode
half of the same gap is PR flashinfer-ai#3817.
Fixes flashinfer-ai#3828
Signed-off-by: OsakaTX <OsakaTX@users.noreply.github.com>
There was a problem hiding this comment.
Code Review
This pull request adds support for a topk value of 256 using FP8 precision in the dispatch_dsv4_single function within csrc/sparse_mla_sm120_prefill.cu. Additionally, it updates the test configurations in tests/attention/test_sparse_mla_sm120.py to include test cases for this new configuration. There are no review comments, and I have no feedback to provide.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdded an ChangesDSV4 Prefill topk=256 Support
Estimated code review effort: 1 (Trivial) | ~5 minutes Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Heads up: #3834 (opened 07-04) implements this same prefill-half of #3828 -- same dispatch branch and the same (16,256)/(32,256) test configs -- but with BF16 CM instead of FP8, picked from measurement on an RTX PRO 6000 (BF16 beat FP8 by 2.5-9% at all six shapes I benched; the small-K-loop prologue argument in the PR body). ormandj's multi-day SM120 serving soak upthread on #3817 ran with the BF16 version of this branch. Not territorial about which PR lands, but the compute-mode choice is a real fork in the road and probably deserves a deliberate call by the maintainers. |
Good catch, and I appreciate the friendliness. Haven't submitted many PRs before, mostly do private dev work. Agree the CM choice is the real decision and it belongs to the maintainers. Your RTX PRO 6000 data is compelling for sm_120. One datapoint is missing: sm_121a (GB10/DGX Spark), which is where the (32,256) shape actually bites in practice (DSv4 DSpark under vLLM TP=2). I'll try and bench both CM variants at the six shapes on GB10 hardware and post numbers here within a day or two. If BF16 holds on sm_121a as well, #3834 is the better patch and I'm happy to close this one in its favor. The fix landing matters more than whose branch carries it. |
|
sm_121a numbers would genuinely complete the picture -- it's a different chip and a different cubin variant (121a vs 120f), so I wouldn't assume my sm_120 ordering transfers. And the goodwill cuts both ways: if FP8 wins on GB10 I'm happy to flip #3834's CM or split it per-arch, whichever the maintainers prefer. Looking forward to your numbers. |
|
Closing this in favor of #3834. I benchmarked both compute modes for the Method. #3834 and this PR differ by exactly one token in the dispatch ( Result (BF16 time saved vs FP8, positive = BF16 faster):
BF16 is faster than or equal to FP8 in every configuration. The margin is largest at short prefills (about 10 to 19% at 128 to 256 tokens), where the kernel is latency-bound and the FP8 dequant path costs the most, and it narrows toward parity at long prefills (about 0 to 5% at 1024 to 2048 tokens) as the kernel becomes bandwidth-bound. FP8 shows no throughput advantage, so #3834 is the right choice for this dispatch on GB10. Thanks @waynehacking8. |
## 📌 Description This PR consolidates the community work needed to run DeepSeek-V4-Flash-0731 with DSpark through the SM120/SM121 sparse MLA backend. A downstream DSpark configuration has 133 active sparse entries per query: 128 sliding-window entries plus 5 draft entries. The index tensor is padded to 192 because the kernel consumes 64-entry tiles. Other integrations use the 256 bucket. Neither shape was fully represented in the existing SM120 decode and prefill dispatch matrices, so decode-sized requests could miss the standalone kernel and fall through to the prefill-only orchestrator, which aborts on `num_tokens <= 64`. This change: - adds DSV4 decode instantiations for `topk=192` and `topk=256` with 8, 16, 32, 64, and 128 query heads; - adds DSV4 single-cache prefill dispatch for `topk=192` and `topk=256` using BF16 QK; - supports TP8 prefill by padding H8 into the existing 16-head MG tile while gating all global Q, sink, output, and LSE accesses; - enables the padded H8 MG path for both single-cache and dual-cache prefill, including both supported secondary-cache page sizes and runtime top-k lengths; - keeps the Python and CUDA dispatch matrices and user-facing documentation synchronized; - raises an actionable Python `ValueError` when an unsupported decode shape would otherwise enter the prefill-only kernel and abort the process; - fixes the sparse MLA benchmark KV cache view to match its default HND layout; and - expands correctness and benchmark coverage for the new dispatch shapes, active-length truncation, HND/NHD layouts, caller-owned workspaces, and output-buffer reuse. ## 🔍 Related Issues and Community PRs After coordination with the maintainers, this PR is intended as the single consolidated replacement for the overlapping open implementations: - #4309 — DSV4 `topk=192` decode/prefill and active-length coverage. - #4372 — broad DSV4 `topk=256` decode/prefill dispatch and public API coverage. - #3989 — combined DSpark `topk=256` fix and benchmark HND layout correction. - #3817 — DSV4 `topk=256` decode instantiations and decode-to-prefill fail-fast behavior. - #3834 — DSV4 `topk=256` BF16 prefill dispatch. It also covers the implementation scope of the earlier closed alternatives #3896 and #3923. Related reports include #3828, #3988, and #4336. The NVFP4 KV-cache extension in #3937 is a separate feature and is not superseded by this PR. ## 🚀 Pull Request Checklist ### ✅ Pre-commit Checks - [x] I used the repository-compatible `prek` hook runner. - [x] All hooks relevant to the changed files pass, including clang-format, mypy, ruff check, and ruff format. - [x] `git diff --check` passes. ## 🧪 Tests - [x] Tests have been added or updated as needed. - [x] `pytest -q tests/attention/test_sparse_mla_sm120.py`: 309 passed on SM120. - [x] `compute-sanitizer --tool memcheck` on representative H8 single-cache, dual-cache PBS64, dual-cache PBS2, and runtime-length cases: 4 passed, `ERROR SUMMARY: 0 errors`. - [x] The complete `benchmarks/bench_sparse_mla_sm120.py` sweep runs successfully, including the corrected HND path and H8/H16 single- and dual-cache cases. ## Reviewer Notes The main review focus is the padded H8 MG specialization. The kernel still computes a 16-head tile, but only the first 8 rows may touch caller-owned global tensors; the remaining rows are zero-filled in shared memory and excluded from sink, output, and LSE accesses. Tests cover sinks, active-length truncation, the public HND API, dual-cache full-tile and runtime-length paths, and both secondary-cache page sizes. AI tools were used to assist with implementation, testing, and PR preparation. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Expanded sparse MLA support for additional head counts and top-k values, including 192, 256, and 2048. * Added support for eight-head configurations and more prefill, token-count, page-size, and dual-cache scenarios. * Improved compatibility with HND and NHD layouts. * **Bug Fixes** * Unsupported decode shapes are now rejected before processing. * Improved truncation handling for top-k and extra top-k lengths. * **Tests** * Expanded coverage for layouts, buffer reuse, workspace, sequence lengths, decode, and prefill scenarios. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: David Orman <ormandj@corenode.com> Co-authored-by: JimZhang-lab <60953754+JimZhang-lab@users.noreply.github.com> Co-authored-by: Albert Catalan Tatjer <ac.tatjer@gmail.com> Co-authored-by: carlosmolina0615 <carlosmolina0615@gmail.com> Co-authored-by: Wei-Cheng (Wayne) Chiu <waynehacking8@gmail.com> Co-authored-by: OsakaTX <OsakaTX@users.noreply.github.com> Co-authored-by: Martin Vit <martin@voipmonitor.org>
📌 Description
Implements the prefill half of #3828, exactly as proposed there by @eous: the
SM120 sparse-MLA DSV4 prefill path (
dispatch_dsv4_singleincsrc/sparse_mla_sm120_prefill.cu) has notopk == 256branch — the dispatchchain covers {128, 512, 1024, 2048} — so a prefill-shaped call
(
num_tokens > 64) withtopk=256returns false and fails:As #3828 notes,
topk=256is a valid shape (4 × BI(64), between theinstantiated 128 and 512); it's simply missing from the grid. The shape occurs
in practice via DeepSeek-V4-Flash-DSpark under tensor-parallel=2 — the decode
half of the same gap is addressed by #3817.
Change
csrc/sparse_mla_sm120_prefill.cu:else if (topk == 256) DISPATCH_BY_NH_CM(FP8, 256);in
dispatch_dsv4_single— FP8 compute mode per the existing comment (theBF16 QK fast path is reserved for the small K-loop at 128; FP8-512 already
builds, so the smaller 256 tile is smem-safe).
tests/attention/test_sparse_mla_sm120.py: add(16, 256)and(32, 256)to
_DSV4_PREFILL_CONFIGS(16 exercises the MG_N_HG_T=1 routing, 32 is themotivating TP=2 shape).
🧪 Testing
Isolation A/B on GB10 (sm_121a), CUDA 13 — identical container and environment,
module JIT-built from source in both legs, only the two dispatch lines varied.
This complements the RTX PRO 6000 (SM120) serving validation reported in #3828 —
two architectures, same result:
topk=256prefill combos fail (
num_tokens ∈ {128, 256}×with_sink ∈ {False, True}×NH ∈ {16, 32}) with the error above; all 36 pre-existing prefill combos pass.
bf16 reference implementation.
🔗 Related
implements it with test coverage and additional hardware validation)
confirmed on my hardware in that thread)
Summary by CodeRabbit
topk=256, for certain sparse attention workloads.topk=256combinations to improve validation of the new supported settings.