Repository navigation
[Perf][Attention] Use native small-head FlashMLA on H20 and H100 - #67468
Open
zhangxin81 wants to merge 1 commit into
Open
zhangxin81 wants to merge 1 commit into
zhangxin81 wants to merge 1 commit into
Conversation
Enable ETAP for nonempty 8/16-head BF16 sparse calls on the measured full H20 and H100 devices. Retain other-device and 32-head thresholds. Extend output-buffer/graph replay coverage and add a reusable kernel benchmark. Co-authored-by: Codex <noreply@openai.com> Signed-off-by: zhangxin.zzzzz <115389973+zhangxin81@users.noreply.github.com>
Contributor
|
Documentation preview: https://vllm--67468.org.readthedocs.build/en/67468/ |
Contributor
|
This pull request has merge conflicts that must be resolved before it can be |
This branch has not been deployed
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.
Overview
Use native SM90 BF16 sparse FlashMLA for nonempty 8/16-head batches on full H20 (78 SMs) and H100 SXM 80GB (132 SMs). This reuses the ETAP kernel integrated by #67175; 32-head and other-device cutoffs remain.
Full-weight H20 evaluation/serving was not run because only one H20 was available. H20 coverage uses kernel tests and a two-layer random-weight LLM fixture.
Claims
Validation
GLM uses the official FP8 checkpoint revision
46a050bec13002ad29ee795c16e61cf4fa3c4a9cwith BF16 KV. Every rank has 11 affected layers. VLLM_GPU_SYNC_CHECK=error remains enabled. Real-input FP32/padded/native probes pass 176 cases at existing output/LSE tolerances; actual/native replay outputs are identical. A same-weight eager native/padded/native-repeat intervention reproduces greedy/LP changes, while native-repeat is identical. The full checkpoint fails the toy fixture's 0.01 LP comparison; no tolerance was widened. GSM8K point estimate is lower by 0.4549 percentage points; paired-discordance p=0.496617 does not establish equivalence.Serving uses TP8, batch budget 128, maxseq 128, maxlen 16384, BF16 KV, graphs, chunked prefill, no prefix cache, no FlashInfer autotune, memory 0.85, normal engine multiprocessing, Python frontend. Three paired rounds cover 24 workloads, 960 requests, 122880 output tokens; all counts/zero failures/fixed lengths/equal input counts pass. Temperature is not supplied, so the model/server default is used; seed 42 controls random input sampling.
Concurrency 16/64 has large variation with gains and regressions. No server JIT-monitor warnings or preemptions were found. A reused client's logger reports closed-stream errors during input sampling before warmup/timing on 18 invocations; timing placement was audited, original logs retained, and a separate fix is supplied for future runs. A port preflight failure and an I/O-overlapping second round were retained/excluded explicitly; the latter was rerun after copying stopped.
The extended regression was installed in both source trees. On H20 and H100 the original selector fails the 16 newly expected small-batch native cases while actual output/LSE comparisons pass; the candidate passes all 144 cases. The failure identifies padded work through overwritten unused output heads, not output corruption on the baseline. Representative H100 output:
.venv/bin/python -m pytest tests/v1/attention/test_sparse_mla_backends.py \ -k flashmla_bf16_preserves_unused_output_heads -v .venv/bin/python -m pytest \ tests/v1/attention/test_sparse_mla_backends.py \ tests/v1/attention/test_flashmla_nope_sm90_backend_selection.py \ tests/kernels/attention/test_flashmla_sparse.py \ -k 'flashmla and not bf16_preserves_unused_output_heads' -v .venv/bin/python benchmarks/kernels/benchmark_flashmla_small_heads.py \ --heads 8 16 32 --dims 512 576 --topk 128 640 2048 8192 8320 \ --tokens 1 8 32 64 128 132 --rounds 3 --repeats 30 --output h100.csvFor H20 use tokens 1/8/32/64/78/128. Changed-file pre-commit (Ruff, mypy, Markdown, SPDX, test tethering and others) and git diff --check pass. Current-source CMake completed 470 steps; both arms use FlashMLA b18ed744 and identical binary SHA256
276f51f87eaa0ca1a852c43a6e3d2c0d27a1d85be92d250c2a0ba4f9a528a1f2. Large matrices use FlashInfer 0.7.2.post1; model/serving and the 24 exact-width 2176 supplemental shapes per GPU use 0.7.4. These matrices pass: H100 geometric mean 1.431x; H20 3.796x across all shapes and 3.785x over the 20 shapes with changed dispatch. The four H20 query-128 shapes already used native kernels.Details
Device name/SM count is read at construction, excluding MIG partitions by SM count rather than physical name alone. Selection reads shape/device metadata and adds no GPU tensor host read. At 32 heads retain tokens>2*SM; other SM90 devices retain tokens>SM for 8/16 heads. BF16 native/padded reduction orders can change rounding and greedy output; FP8 KV-cache decode dispatch is unchanged.
H100 32-head T1,D576,K128 regresses from 8.000 us padded to 10.945 us native, supporting the retained cutoff. Empty-key 16-head H100 cases regress 0.048–0.096 us; no host synchronization is added to branch on key counts.
Duplicate searches found no equivalent common ETAP threshold PR. #57673 is a separate Triton DSv4.1 backend; #59418/#62941 target its decode, #67338 refactors routing metadata, #65403 changes index-group workspace/masked MHA, #59319/#60220 change FP8 mixed-batch workspace/staging. DeepSeek-V4.1 uses its dedicated attention class and already selects native BF16 prefill heads on SM90; GLM exercises this common implementation.
AI assistance was used to implement the change and run experiments. The human submitter confirmed line-by-line review and personally running relevant tests. Full H20 checkpoint/serving coverage remains a documented limitation. Fresh-agent documentation discovery passed locally and on the public PR branch. Rendered-preview discovery is pending: the upstream pre-run check stops lint and the docs build before execution because this author has 2 merged PRs rather than 4 and the PR lacks the required review labels. See the pre-run log and docs build. Local changed-file lint passed; these upstream jobs have not evaluated the code or rendered docs.
Full-model and serving reproduction
The measured base is
1786f260e3d68fa4d5a97191ddbffd7179edc96a. Both Python trees use the same source-built extensions; only the dispatch file differs. Downloadzai-org/GLM-5.3-Flashrevision46a050bec13002ad29ee795c16e61cf4fa3c4a9cand setMODEL_PATHto the local checkpoint. Model evaluation uses the repository's_build_gsm8k_prompts(1319, 5)and_score_gsm8khelpers, raw completions, and the following configuration. Run on each arm withVLLM_GPU_SYNC_CHECK=error,VLLM_ENABLE_V1_MULTIPROCESSING=0, andNCCL_NVLS_ENABLE=0:For the TP4 coverage check, use TP4/PP1, eager execution,
kv_cache_memory_bytes=512*1024**2, memory utilization 0.965, max length 512, batch-token budget 64 and max sequences 1. Run the same smoke prompts only. This is a coverage check, not a TP4 serving benchmark.Serving uses normal engine multiprocessing and Python frontend/benchmark (
VLLM_ENABLE_V1_MULTIPROCESSING=1,VLLM_USE_RUST_FRONTEND=0,VLLM_USE_RUST_BENCH=0), withVLLM_GPU_SYNC_CHECK=errorandNCCL_NVLS_ENABLE=0:The measured client imports
vllm.entrypoints.cli.main.mainonce per server arm and invokes the CLI for each(input length, concurrency, requests)tuple:(128,1,16),(2048,16,64),(9216,1,16),(9216,64,64). The CLI resets seeds for each invocation. Equivalent per-workload arguments are:Run three paired rounds in base/candidate, candidate/base, base/candidate order. Round 0 uses shared source/runtime; rounds 1/2 use byte-identical local Python caches, balanced within each pair, with original binary origins retained. Startup/import/warmup time is outside measurement. An interrupted round overlapping cache-copy I/O was archived and excluded; both arms were rerun after copying stopped. Original result/log files, numerical probes and failed setup logs are retained locally rather than added to the source diff.
Pull Request Checklist
I used vLLM's
/pr-checklistskill. (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.