Skip to content

[Attention] Enable FA4 sparse MQA decode on Blackwell - #55866

Open
simon-veitner-redhat wants to merge 12 commits into
vllm-project:mainfrom
simon-veitner-redhat:sparse-mqa
Open

simon-veitner-redhat wants to merge 12 commits into
vllm-project:mainfrom
simon-veitner-redhat:sparse-mqa

Conversation

@simon-veitner-redhat

@simon-veitner-redhat simon-veitner-redhat commented Sep 8, 2026 •

Copy link
Copy Markdown
Contributor

[Attention] Enable FA4 sparse MQA decode on Blackwell

This adds FLASH_ATTN_MLA_SPARSE_FA4, a sparse MLA backend for Blackwell with a BF16 KV cache. The FA4 CuTe DSL kernel from vllm-project/flash-attention#195 serves decode batches and the decode rows of mixed HiSparse batches. Every other batch runs on the trtllm-gen lane, as in FLASHINFER_MLA_SPARSE. At 16 or fewer query heads per rank the backend is the first choice, with and without HiSparse; above that head count it stays opt-in.

The first commit, "Share sparse MLA MQA cache handling", will go up as its own PR and is only here until it lands. It moves index conversion and the HiSparse lane split from the FA3 and FlashInfer sparse MLA backends into SparseMLACommonImpl.forward_mqa, so a backend implements only _forward_mqa_kernel(..., is_decode). The design is by @LucasWilkinson. One FA3 behaviour changes with it: FA3's plain path converts top-k through the index group's shared buffer, as FlashInfer already did, instead of once per layer. The values are identical while the layers of a group share block stride, block table and request ids, which index groups guarantee. A test pins leader and follower layers.

The second commit is the FA4 backend on top of that hook:

  • flash_attn_varlen_func forwards gather_kv_indices, gather_kv_valid_length and q_v to FA4.
  • The impl subclasses FlashInferMLASparseImpl. Its hook runs the FA4 decode kernel when is_decode, otherwise FlashInfer's trtllm-gen call with the LSE converted to base e.
  • The metadata builder subclasses the FlashInfer TRTLLM builder and declares UNIFORM_BATCH CUDA graph support. Inheriting the builder brings the DCP workspace pre-size: an earlier version of this PR used the default 394 MiB trtllm workspace on its prefill lane and crashed under DCP 2 on a prefill step of about 8192 tokens, where the softmax-stats slab needs 513 MiB.
  • The backend class subclasses the FlashInfer TRTLLM backend for its gates (PCP with DCP rejected, head dims) and adds the FA4 gates: index_topk a multiple of 128, and a supported gathered head count under DCP.
  • Under HiSparse, decode reads the hot buffer through the shared lanes. The inherited autotune_hisparse_decode compiles the FA4 kernel before graph capture.
  • FA4 shares FlashInfer's masked-MHA thresholds.
  • FA4 joins _uses_flat_kv_cache, since it reads the same flat KV cache as FlashInfer.

The last commit bumps the flash-attention pin to vllm-project/flash-attention 2e3a6694, which has #195 and the sparse decode split-rule tuning for DCP shapes (vllm-project/flash-attention#200).

Performance

GLM-5.2 NVFP4-FP8 with BF16 KV on B300, TP4, FA4 against FLASHINFER_MLA_SPARSE from the same tree (this PR on main d71f662), change in median ITL (negative favours FA4). Plain and DCP 2 are averaged over two runs. The HiSparse column assumes #59309 is merged: it applies that PR's diff, pins the MoE autotune tactics so both backends run the same MoE kernels, and averages two server starts with two runs each.

Input / concurrency / output TP4 plain TP4 DCP 2 TP4 HiSparse
4096 / 8 / 256 -4.2% -6.7% -0.8%
4096 / 128 / 256 -4.3% -2.3% +1.3%*
32768 / 16 / 256 -5.3% -5.1% +0.2%

* One FA4 run measured 35.2 ms against 33.4 to 33.7 ms for the other three; without it the figure is +0.1%.

Under HiSparse FA4 is on par with FlashInfer, which did not justify a separate priority order. Per decode step, FA4's attention kernels take about 190 µs less than FlashInfer's at 4096 / 8, but start-to-start variance in all-reduce time is larger than that difference. On current main, #59235 makes HiSparse about 0.45 ms per decode step slower for both backends, because it writes request_ids in every layer. #59309 moves those writes into the group leader's resolve, which brings the 57 follower layers' 171 kernels per step back out of the decode graph.

Validation

  • pytest tests/v1/attention/test_sparse_mla_backends.py: 475 passed, 672 skipped. pytest tests/v1/e2e/general/test_hisparse.py: 5 passed (FlashInfer and FA4). The FlashInfer, KV cache layout, backend selection and masked-MHA routing tests pass as well.
  • Serving, GLM-5.2 NVFP4-FP8, TP4, HiSparse, GSM8K (500 questions, 5-shot): FA4 0.936, FA4 with MTP 0.948, FlashInfer 0.946. No invalid responses; 8K, 16K and 30K needle prompts answered correctly.
  • FlashInfer on the shared base: latency within noise of main, plain generations byte-identical.
  • The FA3 sparse backend did not run on hardware here (SM90 kernel, SM100 machine); its change is covered by unit tests only.

AI-assisted. The September 7 upstream search found no matching open FA4 sparse-MLA integration PR; related platform-specific work does not provide this SM100 backend.

@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 commented Sep 12, 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, @simon-veitner-redhat.

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

@mergify

mergify Bot commented Sep 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, @simon-veitner-redhat.

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

simon-veitner-redhat and others added 2 commits October 9, 2026 07:37
Drop mock-only tests that pin internals and duplicate coverage, fold the
HiSparse decode-only tests into the lanes test, split the shared converter
mock in the FA4 routing test, and replace the SM100 priority restatement
with a fallback test.

Signed-off-by: Simon Veitner <sveitner@redhat.com>
Co-Authored-By: Claude <noreply@anthropic.com>
@LucasWilkinson

Copy link
Copy Markdown
Contributor

/ci run

@LucasWilkinson
LucasWilkinson enabled auto-merge (squash) October 9, 2026 14:28
@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

✅ Triggered Buildkite CI #93859 for commit 0d695c43750b.

auto-merge was automatically disabled October 9, 2026 17:08

Head branch was pushed to by a user without write access

The FA4 sparse MLA backend imports vllm.vllm_flash_attn, which is not
built on ROCm, so importing it at module level broke test collection
there. Parametrize over AttentionBackendEnum and resolve the backend
class inside the test, and mark the FA4 case CUDA only, so the CPU cases
for the other backends keep running on ROCm.

Signed-off-by: Simon Veitner <sveitner@redhat.com>
@LucasWilkinson

Copy link
Copy Markdown
Contributor

/ci retry

@mergify

mergify Bot commented Oct 9, 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, @simon-veitner-redhat.

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 9, 2026
Signed-off-by: Lucas Wilkinson <lwilkins@redhat.com>

# Conflicts:
#	tests/v1/attention/test_sparse_mla_backends.py
#	tests/v1/attention/test_sparse_mla_kv_cache_layout.py
#	vllm/v1/attention/backends/mla/flashattn_mla_sparse.py
#	vllm/v1/attention/backends/mla/flashinfer_mla_sparse.py
@mergify mergify Bot removed the needs-rebase label Oct 9, 2026
@LucasWilkinson

Copy link
Copy Markdown
Contributor

/ci run

@github-actions

Copy link
Copy Markdown

✅ Triggered Buildkite CI #94036 for commit cf280cf82451.

The test imports vllm.v1.attention.backends.mla.flashattn_mla_sparse, which
imports vllm.vllm_flash_attn; that extension is not built on ROCm, so the
test failed with ImportError on AMD CI. Mark it CUDA only, matching the
neighbouring selection test.

Signed-off-by: Simon Veitner <sveitner@redhat.com>
@MatthewBonanni

Copy link
Copy Markdown
Member

/ci run

@github-actions

Copy link
Copy Markdown

❌ This PR is 57 commits behind upstream main. Your branch must contain every commit currently on upstream main. No new CI build was started. Merge or rebase onto the latest main, then rerun /ci run. To test this branch at your own risk, use /ci run --allow-stale.

@MatthewBonanni

Copy link
Copy Markdown
Member

/ci run

@github-actions

Copy link
Copy Markdown

✅ Triggered Buildkite CI #94216 for commit 4d3b1d8ff9a6.

@vllm-agent

Copy link
Copy Markdown
Contributor

CI selector (shadow): 194 test steps (270 jobs) instead of 195 (271 jobs)

Shadow mode: this changes nothing about what CI runs. It shows what the evidence-based selector would pick for this PR, next to today's rules. How it works.

Feedback welcome: reply here if it would skip a step this change needs, or runs something unrelated.

steps (jobs) Today's rules Selector Would skip Would add
NVIDIA, CPU and others 195 (271) 194 (270) 1 (1) 0 (0)
AMD mirrors 161 (225) 158 (222) 3 (3) 0 (0)

Today's rules run everything for this diff.

Selector would run (194)
  • amd-fp8-moe-kernels-mi355
  • amd-kernels-mi355
  • amd-lm-eval-small-models-harness
  • amd-native-quantization-kernels-mi355
  • amd-qwen3-next-mtp-async-eplb-accuracy
  • arm-cpu-test ×3
  • async-engine-inputs-utils-worker
  • basic-correctness ×2
  • basic-correctness-cpu-offload
  • basic-correctness-cumem
  • basic-correctness-prefetch-offload
  • basic-correctness-sleep-mode
  • basic-models-test-other-cpu
  • basic-models-tests-extra-initialization ×14
  • basic-models-tests-initialization
  • basic-models-tests-other
  • batch-invariance-b200
  • batch-invariance-h100
  • benchmarks-cli-test
  • cpu-distributed-tests-dp-tp
  • cpu-distributed-tests-pp-tp
  • cpu-kernel-tests ×2
  • cpu-language-generation-and-pooling-model-tests ×3
  • cpu-multi-modal-model-tests-n ×4
  • cpu-multimodal-config
  • cpu-params-env-tokenizers-parser
  • cpu-quantization-model-tests
  • cpu-qwen2-5-vl-multimodal-tests
  • cpu-reasoning-renderers
  • cpu-spec-decode-tests
  • cpu-tool-parsers
  • crcr-report
  • crosslayer-kv-layout-distributed-nixlconnector-pd-accuracy-tests-4-gpus
  • cudagraph
  • deepseek-v4-kernel-test-b200
  • deepseek-v4-kernel-test-h100
  • distributed-comm-ops
  • distributed-compile-comm-4-gpus
  • distributed-compile-rpc-tests-2-gpus
  • distributed-compile-unit-tests-2xh100
  • distributed-dp-tests-2-gpus
  • distributed-dp-tests-4-gpus
  • distributed-flashinfer-nixlconnector-pd-accuracy-4-gpus
  • distributed-model-tests-2-gpus ×3
  • distributed-mooncakeconnector-pd-accuracy-4-gpus
  • distributed-nixlconnector-pd-accuracy-4-gpus
  • distributed-torchrun-examples-4-gpus
  • distributed-torchrun-shutdown-tests-2-gpus
  • docker-build-metadata
  • dp-ep-distributed-nixlconnector-pd-accuracy-tests-4-gpus
  • dsv41-mono-decode-numerics-amd
  • e2e-core-1-gpu
  • e2e-core-large-memory
  • e2e-scheduling-1-gpu
  • e2e-scheduling-accuracy-1-gpu
  • elastic-ep-scaling-test
  • engine
  • engine-1-gpu
  • entrypoints-integration-api-server ×4
  • entrypoints-integration-api-server-generate
  • entrypoints-integration-api-server-openai-chat_completion
  • entrypoints-integration-api-server-openai-completion
  • entrypoints-integration-llm
  • entrypoints-integration-multimodal
  • entrypoints-integration-pooling
  • entrypoints-integration-responses-api
  • entrypoints-integration-speech_to_text
  • entrypoints-unit-tests
  • eplb-algorithm
  • eplb-execution
  • examples
  • extract-hidden-states-integration
  • extract-hidden-states-integration-2-gpus
  • fault-tolerance-e2e-2xh100
  • fusion-and-compile-unit-tests-2xb200
  • fusion-e2e-config-sweep-h100
  • fusion-e2e-quick-h100
  • fusion-e2e-tp2-ar-rms-config-sweep-h100
  • fusion-e2e-tp2-ar-rms-dynamo-partition-amd
  • fusion-e2e-tp2-ar-rms-inductor-partition-amd
  • fusion-e2e-tp2-b200
  • fusion-e2e-tp2-quick-h100
  • gemm-rs-ar-2xb200
  • glm5next-unit-tests
  • hybrid-ssm-nixlconnector-pd-accuracy-tests-4-gpus
  • hybrid-ssm-nixlconnector-pd-prefix-cache-2-gpus
  • inkling-unit-tests-b200
  • intel-hpu-test
  • jit-monitor-no-runtime-jit
  • kernels-attention-diffkv-test-h100
  • kernels-attention-test ×7
  • kernels-b200 ×3
  • kernels-core-operation-test ×3
  • kernels-deepgemm-test-h100
  • kernels-fla-ops-test-b200
  • kernels-flashmla-test-h100
  • kernels-fusedmoe-layer-test-2-b200s
  • kernels-fusedmoe-layer-test-2-h100s
  • kernels-helion-test ×5
  • kernels-mamba-test
  • kernels-mhc-test-b200
  • kernels-minimax-m3-attention-b200
  • kernels-minimax-reduce-rms-test-2-gpus
  • kernels-moe-test ×5
  • kernels-quantization-test ×6
  • kernels-root-misc-test-b200
  • kimi-k3-prefix-cache-4xb200 ×2
  • kimi-k3-unit-tests-b200
  • kv-offload-large
  • kv-offload-medium
  • kv-offload-small
  • language-models-tests-extra-standard ×2
  • language-models-tests-granite-l4-compatibility
  • language-models-tests-hybrid ×2
  • language-models-tests-standard
  • lm-eval-dspark-watermark-2xh100
  • lm-eval-small-models
  • lm-eval-turboquant-k3v4nc
  • lm-eval-turboquant-k8v4
  • lm-eval-turboquant-t3nc
  • lm-eval-turboquant-t4nc
  • lm-eval-watermarking
  • lora ×4
  • lora-tp-distributed ×4
  • metrics-tracing-2-gpus
  • model-executor
  • mooncake-ec-tcp-e2e-2-gpus
  • mrcr-eval-small-models
  • multi-modal-accuracy-eval-small-models
  • multi-modal-models-standard-1-qwen2
  • multi-modal-models-standard-2-qwen3-gemma
  • multi-modal-models-standard-3-llava-qwen2-vl
  • multi-modal-models-standard-4-other-whisper
  • multi-modal-processor ×4
  • multi-modal-processor-cpu ×4
  • multiconnector-nixl-offloading-pd-accuracy-2-gpus
  • multiconnector-nixl-offloading-pd-edge-cases-2-gpus
  • nixlconnector-pd-edge-cases-2-gpus
  • openai-api-correctness
  • pipeline-context-parallelism-4-gpus
  • platform-tests
  • plugin-tests-2-gpus
  • push-nixlconnector-pp-prefill-pd-accuracy-4-gpus
  • pytorch-compilation-dynamic-shapes
  • pytorch-compilation-passes-unit-tests
  • pytorch-compilation-unit-tests
  • pytorch-compilation-unit-tests-h100
  • pytorch-fullgraph-cudagraph-l4-compatibility
  • pytorch-fullgraph-test
  • pytorch-nightly-dependency-override-check
  • quantization ×4
  • quantized-fusions
  • quantized-models-test
  • quantized-moe-test-b200
  • qwen4-exp-sp-tests-4-gpus
  • qwen4-exp-unit-tests
  • qwen4-exp-unit-tests-cpu
  • ray-dependency-compatibility-check
  • rayexecutorv2-4-gpus
  • regression
  • replayssm-e2e
  • rl-entrypoints-tests
  • rust-frontend-cargo-style-clippy
  • rust-frontend-cargo-tests
  • rust-frontend-core-correctness
  • rust-frontend-distributed
  • rust-frontend-openai-coverage
  • rust-frontend-serve-admin-coverage
  • rust-frontend-tool-use
  • samplers-multimodal-beam-search
  • samplers-test
  • scale-out-ec-e2e-2-gpus
  • sharded-rdt-weight-transfer
  • spec-decode-draft-model ×4
  • spec-decode-eagle-1-deepseek-qwen
  • spec-decode-eagle-2-llama3-qwen-vl-other
  • spec-decode-mtp-deepseek-mimo
  • spec-decode-mtp-gemma4
  • spec-decode-mtp-qwen3-5
  • spec-decode-ngram-suffix
  • spec-decode-speculators
  • torch-stable-abi-audit
  • v1-attention-b200 ×2
  • v1-attention-h100-mi300 ×2
  • v1-core
  • v1-executor-worker
  • v1-kv-connectors ×4
  • v1-kv-offload
  • v1-logits-oracle
  • v1-metrics-lmeval
  • v1-others-cpu
  • v1-sample
  • v1-spec-decode
  • vllm-ir-tests
Would skip (today's rules run them) (1)
  • ascend-npu-test
Would add (today's rules do not run them) (0)

none

AMD mirrors: would skip (3)
  • pytorch-nightly-dependency-override-check
  • ray-dependency-compatibility-check
  • torch-stable-abi-audit
AMD mirrors: would add (0)

none

14 changed files · base 092c35dd15 · head 4d3b1d8ff9 · Python record: build 93039 at 1e5d0ea888 · kernel record: table 74f4404 (build 94125), map 74f4404 · not counted: 11 build steps, 5 A100 steps the generator no longer emits, 134 optional steps the selector would also run

@mergify

mergify Bot commented Oct 12, 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, @simon-veitner-redhat.

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 12, 2026
@simon-veitner-redhat

Copy link
Copy Markdown
Contributor Author

/ci run

@github-actions

Copy link
Copy Markdown

✅ CI is already running for this commit: https://buildkite.com/vllm/ci/builds/94216

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 documentation Improvements or additions to documentation needs-rebase nvidia ready ONLY add when PR is ready to merge/full CI is needed rocm Related to AMD ROCm

Projects

Status: Todo
Status: Ready

Development

Successfully merging this pull request may close these issues.

4 participants