Skip to content

[SM120] Use exact query-head widths for DeepSeek-V4 sparse MLA decode - #36655

Merged
Fridge003 merged 3 commits into
sgl-project:mainfrom
LinPoly:codex/sm120-exact-head-sparse-mla
Sep 10, 2026
Merged

Fridge003 merged 3 commits into
sgl-project:mainfrom
LinPoly:codex/sm120-exact-head-sparse-mla

Conversation

@LinPoly

@LinPoly LinPoly commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Motivation

DeepSeek-V4 on SM120 pads TP4 decode queries from 16 real heads to 64 even
though FlashInfer supports the native width. This makes sparse attention
process four times as many query heads. This change selects the native width
for supported FlashInfer decode shapes and supplies a matching attention sink.

The native-width prefill path introduced by #29927 is preserved. This PR adds
the corresponding optimization for decode-sized batches.

Modifications

  • Use get_platform().is_sm120 for the platform check.
  • Cache the installed FlashInfer DSV4 decode capabilities and select native
    heads for supported batches up to the decode token limit.
  • Preserve native prefill query widths above the SM120 decode boundary and
    padding for unsupported decode shapes/backends.
  • Return attention-sink views from one persistent backing allocation, retaining
    stable pointers across shape transitions and DSpark's no-argument contract.
  • Extend the existing registered GPU test with native-versus-padded comparisons
    for H8/H16, T=1/64/65, and single/dual cache inputs.

Validation of the current revision

Revision 8729ebafc1778481e64507bc1f057cba4c300715 is rebased onto
c0b790cf7fe6dc1516c3ec1f23de9b37baca654a.

On an exclusively held SM120 GPU, using the revised SGLang source with
FlashInfer 0.6.18 and PyTorch 2.13.0+cu130:

python3 test/registered/kernels/ops/attention/test_flash_mla_backends.py -v
Ran 15 tests: 14 passed, 1 pre-existing skip

All 12 native-versus-padded comparisons passed at atol=rtol=5e-2, including
the decode/prefill boundary and attention sinks. The existing skipped test
probes a legacy FlashInfer module name; the new test exercised the actual
FlashInfer implementation. GPU ownership remained exclusive throughout.

All applicable pre-commit hooks passed on the three changed files, including
formatting, lint, AST parsing, and CI registration checks.

Historical serving and performance validation

The following results were measured on the earlier PR revision 4f5a119dc1
against base 8005df61d3. They have not been rerun for the current rebase.

Official sgl-project/sgl-eval AIME25 repeat-8, using the same four RTX PRO
6000 GPUs and model/server settings, produced 235/240 (97.92%) pass@1,
100% pass@8, and 100% majority@8 on both variants
, with zero request errors.
See the full accuracy qualification.

Unprofiled decode-only A/B used DeepSeek-V4-Flash, pure TP4, FP8 KV, page size
256, FlashInfer sparse MLA and flashinfer_mxfp4 MoE, speculative decoding
disabled, and CUDA graphs/autotuning enabled. Each case had one full-output
warmup wave, then five timed requests per concurrency slot with 1,024 output
tokens and byte-identical prompts across variants.

KV / output C Main output tok/s Patch output tok/s Throughput change Main mean TPOT Patch mean TPOT
1K / 1K 32 1,219.85 1,453.25 +19.13% 26.206 ms 21.994 ms
1K / 1K 64 1,653.77 1,944.41 +17.57% 38.679 ms 32.893 ms
8K / 1K 32 1,213.97 1,379.15 +13.61% 26.342 ms 23.186 ms
8K / 1K 64 1,517.69 1,753.77 +15.56% 42.146 ms 36.468 ms

Every point completed its exact request/token totals, reached its declared
concurrency, and had zero request errors. These are one-repeat synthetic-KV
decode diagnostics, not PD or full-capacity measurements.

Checklist

  • Format code with pre-commit.
  • Add numerical tests in an existing registered suite.
  • Document behavior in code; no user-facing configuration/API change.
  • Provide accuracy and speed results, labeled by the measured revision.
  • Follow the SGLang code-style guidance.

CI States

Latest PR Test (Base): 🚫 Run #34521154609
Latest PR Test (Extra): 🚫 Run #34521154456
Latest PR Test (AMD ROCm 10): 🚫 Run #34521154825

@ispobock

Copy link
Copy Markdown
Collaborator

/rerun-failed-ci

@LinPoly

LinPoly commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Additional accuracy qualification: AIME25 repeat-8

I ran a matched baseline/candidate AIME25 repeat-8 evaluation with the official sgl-project/sgl-eval at commit a231b7a439b235090ff7baa30778fa2b514309ae.

Setup:

  • DeepSeek-V4-Flash, pure TP4 on the same four RTX PRO 6000 SM120 GPUs
  • 30 AIME25 problems x 8 repeats = 240 samples per variant
  • 64 client threads
  • official deepseek-ai/DeepSeek-V4-Flash-0731 preset, unchanged: temperature 1.0, top-p 0.95, thinking enabled, reasoning effort max, and max_tokens=200000
  • same server settings as the PR benchmark: FP8 E4M3 KV, page size 256, FlashInfer sparse MLA/autotuning, flashinfer_mxfp4 MoE, CUDA graphs enabled, speculative decoding and radix cache disabled

Command:

sgl-eval run aime25 \
  --base-url http://127.0.0.1:PORT/v1 \
  --load-preset-from-model-id deepseek-ai/DeepSeek-V4-Flash-0731 \
  --n-repeats 8 --num-threads 64 \
  --out-dir OUTPUT_DIR
Metric Main (8005df61) Patch (4f5a119d)
Correct / samples 235/240 235/240
pass@1 97.92% 97.92%
pass@8 100% 100%
majority@8 100% 100%
Normal-stop wrong answers 0 1
200K-token truncations / no answer 5 4
Request errors 0 0

All five main misses were 200K-token no-answer truncations. The patch had four such truncations plus one normal-stop stochastic miss (AIME25 problem 14, repeat 3: 163 instead of 735, after 86,758 tokens). Since the official preset is unseeded at temperature 1.0, these are independent stochastic runs rather than paired generations. The equal pass@1 and perfect pass@8/majority@8 show no accuracy regression in this qualification, though they do not establish exact equivalence below the resolution of 240 samples.

As a diagnostic only, the patch generated 0.42% more completion tokens while finishing 8.14% sooner, for 1,110.69 versus 1,015.97 output tok/s (+9.32%). The dedicated frozen decode-only A/B in the PR body remains the performance authority.

Both accepted runs completed all eight 30-record shards with zero HTTP/evaluator errors. Archived server logs contain no traceback, OOM, runtime/assertion failure, unsupported sparse-MLA shape, or request retraction.

@Fridge003

Copy link
Copy Markdown
Collaborator

Hi @LinPoly , we will be merging this PR #29927, I think it can cover the part of using exact query-head?

@LinPoly

LinPoly commented Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

Hi @LinPoly , we will be merging this PR #29927, I think it can cover the part of using exact query-head?

Hi @Fridge003 Baizhou, I discussed with the PR author @AliceChenyy before and the conclusion is the two PRs should be complementary, #29927 is about removing padding for the prefill kernel while this PR is for the decode kernel, Alice can comment on this too @AliceChenyy .

@Fridge003

Copy link
Copy Markdown
Collaborator

Please resolve conflicts

Comment thread python/sglang/srt/models/deepseek_v4.py Outdated
Comment thread test/registered/unit/models/test_deepseek_v4_sparse_mla_heads.py Outdated
lllllinux added a commit to lllllinux/sglang that referenced this pull request Sep 9, 2026
…ecode

Port of upstream PR sgl-project#36655 to the ormandj-v0.8.1-rc.10 stack. On SM120 with
the FlashInfer backend, TP>1 decode currently pads each rank's query heads
to 64 before dispatching the sparse MLA kernel, making the kx kernel process
four times as many heads (e.g. 16 real heads become 64 on TP4). Recent
FlashInfer DSV4 decode dispatchers support the native per-rank widths.

Select the native width only when the installed FlashInfer dispatcher
explicitly supports the active decode shape (capability discovery fails
closed), and keep 64-head padding for prefill-sized batches, unsupported
head counts, and other backends. Retain the branch's existing SM120 prefill
behavior (no padding above the 64-token decode cutoff). Keep one
fallback-width attention-sink allocation and return exact-width views from
it so prefill/decode alternation and CUDA graph capture do not reallocate
or invalidate a captured pointer. Preserve the no-argument
_local_attn_sink() contract used by DSpark.

Adds registered unit coverage for head selection and sink-view stability,
plus an SM120 exact-vs-padded kernel equivalence test.
@Fridge003

Copy link
Copy Markdown
Collaborator

Please solve conflicts

@LinPoly
LinPoly force-pushed the codex/sm120-exact-head-sparse-mla branch from 4f5a119 to 8729eba Compare September 10, 2026 07:29
Skip unsupported 8-head and 16-head subtests independently so a supported width retains its numerical coverage. Keep the numerical operations and tolerances unchanged.
@LinPoly

LinPoly commented Sep 10, 2026

Copy link
Copy Markdown
Contributor Author

@Fridge003 conflict resolved and the unittest removed, extended the numerical test a little bit, let me know if you have more comments, THX a lot!

@Fridge003

Copy link
Copy Markdown
Collaborator

/rerun-test test/registered/kernels/ops/attention/test_flash_mla_backends.py test/registered/e2e/models/test_deepseek_v4_flash_fp4_b200.py test/registered/e2e/models/test_deepseek_v4_flash_fp4_megamoe_b200.py test/registered/e2e/models/test_deepseek_v4_flash_fp4_h200.py

@github-actions

github-actions Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Results for /rerun-test test/registered/kernels/ops/attention/test_flash_mla_backends.py test/registered/e2e/models/test_deepseek_v4_flash_fp4_b200.py test/registered/e2e/models/test_deepseek_v4_flash_fp4_megamoe_b200.py test/registered/e2e/models/test_deepseek_v4_flash_fp4_h200.py:

🚀 1-gpu-h100 (1 test): ✅ View workflow run

cd test/ && python3 registered/kernels/ops/attention/test_flash_mla_backends.py

🚀 4-gpu-b200 (2 tests): ✅ View workflow run

cd test/ && python3 registered/e2e/models/test_deepseek_v4_flash_fp4_b200.py
cd test/ && python3 registered/e2e/models/test_deepseek_v4_flash_fp4_megamoe_b200.py

🚀 8-gpu-h200 (1 test): ✅ View workflow run

cd test/ && python3 registered/e2e/models/test_deepseek_v4_flash_fp4_h200.py

@Fridge003
Fridge003 merged commit d076eec into sgl-project:main Sep 10, 2026
85 of 202 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants