Skip to content

[Perf][DSv4.1] MegaAttn: wo_a writes wo_b's MXFP8 input - #60118

Open
Juntian777 wants to merge 9 commits into
vllm-project:mainfrom
Juntian777:dsv41-mega-attn-wo-a-mxfp8
Open

Juntian777 wants to merge 9 commits into
vllm-project:mainfrom
Juntian777:dsv41-mega-attn-wo-a-mxfp8

Conversation

@Juntian777

@Juntian777 Juntian777 commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Overview

MegaAttn's (FLASHMLA_MEGA_ATTN_DSV41) wo_a einsum now writes z directly as MXFP8, together with the F8_128x4 UE8M0 scales that wo_b's FlashInfer MXFP8 GEMM reads. wo_b therefore no longer quantizes a BF16 z, at any token count. It uses vllm-project/DeepGEMM#40 (merged), which adds the 128x4 scale layout to DeepGEMM's FP8 einsum epilogue. This PR bumps the DeepGEMM pin to it.

Claims

  • _o_proj drops the standalone mxfp8_quantize kernel. On GB200 it is 0.4-2.0 us per layer faster in decode (1-256 tokens) and 2.8-141 us faster in prefill (512-32768 tokens). The one regression is +0.6 us at 384 tokens (see Details).
  • wo_b receives byte-identical FP8 data and scales, so model outputs do not change.
  • Only flash_mla_mega_attn.py changes (+33/-5 lines vs main). Shared o_proj code and other backends are untouched.

Validation

_o_proj alone (wo_a einsum, then wo_b CuTe-DSL MXFP8 GEMM) at DeepSeek-V4.1-Flash TP1 shapes: 8 groups x 4096 -> 1024, wo_b 8192 -> 5120. Setup: 1 x GB200, CUPTI, full CUDA graph, cold L2, median of 3 rounds, both arms in one process. Software: torch 2.13.0+cu132, FlashInfer 0.7.0.post1, DeepGEMM a7a9277 + DeepGEMM#40. Outputs are bitwise identical at all 20 sizes measured.

tokens main (us) this PR (us) delta (us) main: einsum BF16 + quant (us) PR: einsum FP8 (us)
1 26.2 24.9 -1.3 10.9 + 2.4 11.2
4 25.5 23.8 -1.7 10.9 + 2.4 11.2
16 26.1 24.1 -2.0 11.0 + 2.5 11.3
64 29.9 28.1 -1.8 12.4 + 2.7 13.0
128 29.3 28.8 -0.5 13.3 + 2.9 14.8
256 46.8 45.1 -1.7 14.3 + 3.6 14.5
384 42.3 42.9 +0.6 17.9 + 4.6 22.3
512 58.5 55.6 -2.8 20.0 + 4.9 20.7
1024 77.7 73.2 -4.5 33.4 + 7.7 34.1
4096 250.1 229.8 -20.3 105.4 + 20.6 104.5
8192 497.4 454.5 -42.9 216.8 + 36.2 210.5
16384 1010.0 906.5 -103.5 439.5 + 68.2 430.4
32768 2127.5 1986.9 -140.6 936.5 + 129.8 903.3

The previous revision of this PR wrote MN-major scales, swizzled them with a separate Triton kernel (1.6-5.2 us per call), and was gated to 1024+ tokens. The E2E prefill (DEP4) and accuracy results below were measured on that previous revision and were not re-run. This revision only removes the swizzle kernel from the same prefill path, and it hands wo_b the same bytes. Decode E2E has not been measured.

Previous revision: E2E prefill (DEP4, GB300) and accuracy

DeepSeek-V4.1-Flash, DEP4 (DP4 x TP1 + EP) on one GB300 node. Default config: SWA bounded replay on, MegaAttn, DeepGEMM mega MoE, fp8 KV cache, max_num_batched_tokens=16384, prefix caching off. Offline LLM per DP rank, one random-token prompt per rank, max_tokens=1. TTFT is measured from scheduled_ts to first_token_ts on the slowest rank; median of 3 repeats after a warmup.

tokens/rank base run 1 (ms) base run 2 (ms) PR (ms) vs base mean
1024 58.7 56.4 57.9 +0.5% (noise)
4096 93.1 92.9 91.4 -1.7%
8192 134.7 135.0 133.5 -1.0%
16384 229.1 227.9 227.4 -0.5%
32768 421.1 421.9 419.5 -0.5%
eval setup score
GSM8K lm-eval 0.4.13, 1319 problems, 5-shot, temperature 0, 4096-token cap, concurrency 32 strict match 92.80%, flexible extract 92.72% (±0.7)
GPQA Diamond gpt-oss GPQAEval, 198 problems, 0-shot chat, thinking on, temperature 1.0, top_p 0.95 89.90% (±2.1)

Tests:

  • Write FP8 einsum output SFs in the 128x4 tiled layout DeepGEMM#40: all 7 tests in tests/test_einsum.py pass, including the new bitwise check of the 128x4 scales against the MN-major path.
  • tests/kernels/test_dsv41_mega_attn_layouts.py::test_quantized_o_proj_matches_quantized_bf16 now covers 1, 129 and 8193 tokens (decode, partial and multiple 128-row tiles), including CUDA graph capture and replay. It checks that _o_proj's FP8 data and valid-row scales are byte-identical to wo_b quantizing the BF16 z. All 5 tests in the file pass on 1 x GB200 (torch 2.14.0+cu132, DeepGEMM with [DO NOT MERGE] Prefix sharing (bug fixed) #40): pytest tests/kernels/test_dsv41_mega_attn_layouts.py -v.
  • pre-commit (ruff, format, typos, shellcheck, mypy) passes.

Details

  • Why the gate is gone. DeepGEMM's einsum could only write MN-major packed scales, so wo_b needed a separate swizzle kernel. Below about 1024 tokens, that launch cost about as much as the quantization it saved. Write FP8 einsum output SFs in the 128x4 tiled layout DeepGEMM#40 changes only the scale address in the einsum epilogue, so no extra kernel is left.
  • Gate conditions (unchanged). The path runs when the einsum uses the per-32 recipe, o_lora_rank % 128 == 0, and wo_b is an MXFP8 kernel that accepts F8_128x4 scales (can_fuse_query_quant). It also requires no GEMM-RS, because the fused GEMM + reduce-scatter takes a BF16 z only.
  • Padded scale rows. Rows past the last token in the final 128-row tile are not written. They only feed wo_b output rows that are never stored, so the test compares valid rows only.
  • 384 tokens. At 128-384 tokens (and at 2048 tokens), DeepGEMM's FP8-output einsum is slower than its BF16-output einsum, for example 17.9 -> 22.3 us at 384. The old MN-major scales show the same slowdown, so it is independent of this change. It is a DeepGEMM kernel-selection issue that can be fixed there.
  • DeepGEMM pin. The pin points at 727f847, the merge commit of DeepGEMM#40 on the fork's dev branch. The einsum selects the 128x4 scales with use_128x4_sfd_layout=True, which an older externally installed deep_gemm (vLLM prefers site-packages) does not accept.
  • Merged main to resolve conflicts.

Pull Request Checklist
  • I used vLLM's /pr-checklist skill. (Mandatory for agents, optional for humans).

  • AI assistance was used during the creation of this PR.

  • Design Fit: Minimizes impact on core components, reuses existing functionality, and justifies added complexity.

  • Testing and Validation: Validates the change and ensures any added tests are meaningful and reliable, with CI coverage or documented CI resource constraints and validation performed outside CI.

  • Code Quality and Style: Keeps code and comments clear and concise, and updates relevant documentation and examples.

  • Pull Request Contents: Includes a brief summary and relevant links, supports claims with evidence, explains root causes and implementation trade-offs, and follows the contributing guide.

🤖 Generated with Claude Code

MegaAttn's wo_a einsum wrote a BF16 z that wo_b then quantized to MXFP8.
From 1024 tokens, the einsum now writes z as MXFP8 with DeepGEMM's packed
UE8M0 scales, a small Triton kernel converts the scales to FlashInfer's
F8_128x4 layout, and wo_b takes the QuantizedActivation directly. The bytes
wo_b sees are unchanged.

- Gated on the per-32 einsum recipe, o_lora_rank % 128 == 0, an MXFP8
  wo_b kernel that takes F8_128x4 scales, and no GEMM-RS (the fused
  GEMM + reduce-scatter takes a BF16 z only).
- Below 1024 tokens (decode, small prefills) nothing changes: the swizzle
  launch costs about what the removed quantization saves there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Juntian Liu <Juntianl777@gmail.com>

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@mergify mergify Bot added deepseek Related to DeepSeek models DSv4.1 Related to DeepSeek-V4.1 models labels Oct 5, 2026
@mergify

mergify Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @Juntian777.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

Juntian777 and others added 2 commits October 16, 2026 09:18
Signed-off-by: Juntian Liu <Juntianl777@gmail.com>
DeepGEMM's FP8 einsum can now write its UE8M0 scales in the F8_128x4
layout that wo_b's FlashInfer MXFP8 GEMM reads (vllm-project/DeepGEMM#40).
The Triton swizzle and the 1024-token threshold go away, so the fused
path also runs in decode. Bump the DeepGEMM pin to that change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Juntian Liu <Juntianl777@gmail.com>
@mergify

mergify Bot commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @Juntian777.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase label Oct 16, 2026
Juntian777 and others added 2 commits October 16, 2026 23:40
vllm-project/DeepGEMM#40 now selects the F8_128x4 scale layout with
`use_128x4_sfd_layout=True` instead of inferring it from a 3D scale
tensor. Pass the knob and bump the DeepGEMM pin to that commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Juntian Liu <Juntianl777@gmail.com>
vllm-project/DeepGEMM#40 merged into the fork's dev branch as 727f847,
whose tree is identical to the previously pinned PR head 4ffc70d.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Juntian Liu <Juntianl777@gmail.com>
Juntian777 and others added 2 commits October 17, 2026 06:06
Take main's removal of tools/install_deepgemm.sh (vllm-project#61265); the DeepGEMM
pin now lives only in cmake/external_projects/deepgemm.cmake.

Signed-off-by: Juntian Liu <Juntianl777@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Juntian777

Copy link
Copy Markdown
Contributor Author

/ci run

@github-actions

Copy link
Copy Markdown

✅ Triggered Buildkite CI #95555 for commit e4084278b376.

@mergify mergify Bot removed the needs-rebase label Oct 17, 2026
@Juntian777

Copy link
Copy Markdown
Contributor Author

/ci retry

@github-actions

Copy link
Copy Markdown

✅ Queued 1 failed job(s) for retry in Buildkite CI #95555.

@zyongye

zyongye commented Oct 17, 2026

Copy link
Copy Markdown
Member

/ci retry

@github-actions

Copy link
Copy Markdown

✅ Queued 1 failed job(s) for retry in Buildkite CI #95555.

@Juntian777

Copy link
Copy Markdown
Contributor Author

/ci run

@github-actions

Copy link
Copy Markdown

✅ Triggered Buildkite CI #95650 for commit 47531fd67ea0.

@Juntian777

Copy link
Copy Markdown
Contributor Author

/ci run

@github-actions

Copy link
Copy Markdown

✅ Triggered Buildkite CI #95681 for commit 1c718c9e9691.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/build deepseek Related to DeepSeek models DSv4.1 Related to DeepSeek-V4.1 models

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants