Conversation
Peuqui
pushed a commit
to Peuqui/1Cat-vLLM
that referenced
this pull request
Sep 23, 2026
The rebuilt Flash-V100 extension requires fp32 partials for E4M3 KV and fp16 otherwise, but `_qsa_xqa_page4_workspace` allocated fp16 unconditionally and keyed its cache without the dtype, so an E4M3 caller was handed a buffer the kernel rejects. Take the wording from 1Cat PR 1CatAI#664 verbatim (issue 1CatAI#648), including the capture-safe `torch.full` for `active_num_partitions`: `torch.tensor([...], device=cuda)` is a host->device copy and illegal during CUDA graph capture, and the stream-keyed cache does rebuild on the graph's side stream. Deployment here runs fp16 KV and therefore never takes this route; both production models stay bit-identical. Taking 1CatAI#664's exact formulation keeps the fork conflict-free when it merges upstream. Checks: ruff check + format clean, mypy clean, tests/models/qwen4_exp/test_qsa_ops.py and test_qsa_e4m3.py 28 passed. Signed-off-by: Peuqui <peuqui@github.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Sep 26, 2026
Leonccaa
pushed a commit
to Leonccaa/1Cat-vLLM
that referenced
this pull request
Sep 26, 2026
Describe target-only DCP2 for Qwen4Exp QSA on TP4 V100: cache ownership, the packed layout and its geometry, the attention path, the related changes (1CatAI#664 for E4M3 KV with MTP; 1CatAI#617/1CatAI#598 for grouped CPU offload, whose DCP pieces this series adds; 1CatAI#684/1CatAI#699 for GDN metadata), the validation gates and results, and the known limits. Assisted-by: OpenAI Codex Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Leon <tomsel1010.us2@gmail.com>
Staging branch for the separate E4M3 + MTP draft-scale enablement; NOT for merge and no PR. Ports two work-in-progress patch sets on top of the null-block-padding fix branch: - phase2: opt-in gate (VLLM_QWEN4EXP_QSA_E4M3_MTP) that relaxes the QSA E4M3 MTP0 requirement, an extracted _verify_e4m3_kv_requirements, the envs entry, an MTP weight-remap hook, calibration-overlay tooling, and CPU/GPU tests. - phase2b: a CUDA-graph-capture-safe XQA workspace (torch.full on-device instead of a host torch.tensor copy) with capture/envelope tests. CPU check (CUDA hidden): 27 passed, 19 skipped (GPU-only), 2 failed. The two failures (test_validate_scale_overlay_lists_missing_names, test_finalize_qsa_scale_load_success_and_missing) exercise draft-side q-scale visibility whose model.py scale-load changes are not part of these two patches; that piece is out of scope for this staging branch. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> (cherry picked from commit 464f538)
Finish the staged draft-scale path without changing the existing main-model fallback contract. Add a repository-owned, revision-checked target/draft scale overlay materializer and make its CPU tests portable. Co-authored-by: OpenAI Codex <noreply@openai.com> Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com> (cherry picked from commit bb4bc78)
The 1CatAI#647 overlay kept the stricter native E4M3 ABI but lost the matching Python workspace dtype selection. Key the cached workspace by KV dtype and allocate FP32 temporary output for E4M3 while retaining FP16 for the existing path. Co-authored-by: OpenAI Codex <codex@openai.com> Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com> (cherry picked from commit b86e641)
test_qsa_e4m3_loader_requires_all_24_scales asserted that an incomplete overlay raises, but left VLLM_QWEN4EXP_QSA_E4M3_STRICT_SCALES unset, so _validate_qsa_e4m3_scale_load took the non-strict warning path and the test failed on main. The gate it claimed to cover was never exercised. Set the env explicitly and assert both contracts: non-strict returns the missing scale names so the caller can fall back to unit scales, strict raises with the loaded/required count. Also assert the non-FP8 cache short circuit returns an empty set rather than only that it does not raise. Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com>
4 tasks
Leonccaa
force-pushed
the
feat/qsa-e4m3-mtp-kv-cache
branch
from
September 26, 2026 23:04
004db58 to
2c1c3f7
Compare
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.
Purpose
Enable calibrated E4M3 KV cache for the Qwen4Exp QSA path with MTP on SM70 (V100), and complete the draft-side scale handling that the staging work left open. It is opt-in (
kv_cache_dtype=fp8_e4m3plusVLLM_QWEN4EXP_QSA_E4M3_MTP=1); without it nothing changes.On 4×V100 TP4 this raises usable KV capacity by 78.8% and prefill throughput by 31–35%, at a decode cost of 1.3–7.0% that scales with context length. It has served our TP4 V100 deployment, with MTP3 and grouped CPU offload, since 2026-09-19.
Status and history
Rebased onto current main (
1e90d17f2c). #647 and #637 are merged, so their commits are gone. Four commits remain:115984a— areslp, E4M3 QSA main KV cache with MTP (phase 2 + 2b), from his staging branchfeat/qsa-e4m3-mtp-draft-scales(0fda07e). Its message still says "NOT for merge and no PR": that described the unfinished staging state, and the next commits finish it. @areslp, if you would rather it not land this way, I can squash it into the completion commit with you as co-author.834e158— draft-side scale finalisation: E4M3 MTP draft loading requires calibrated 2/2 K/V scales and fails closed; the main-model fallback contract is unchanged. Adds the revision-checked scale overlay materialiser (tools/qwen4_exp/materialize_qsa_scale_overlay.py).11f41e1— FP32 XQA workspace for E4M3. Fixes [Bug][SM70] E4M3 KV: XQA page4 route rejects the fp16 tmp_out that qsa.py allocates (kernel expects fp32 since 8a10215d6) #648, which breaks E4M3 on current main even without MTP. The fix is also offered on its own in [Bugfix][SM70] Allocate the QSA XQA page4 workspace for E4M3 KV #705 so it can land first; whichever lands first, the other drops it on rebase.2c1c3f7— tests pinning both halves of the scale-overlay gate.Related work: #702 makes E4M3 without MTP the default first and calls the MTP scale overlay a separate contract; this PR is that contract. #696 (QSA DCP2) merges with this PR without conflicts.
Validation on 4×V100 TP4
Qwen3.8-Flash-Next AWQ g32,
max_model_len262,144, MTP3 withdraft_sample_method=greedy,gpu_memory_utilization0.96.Correctness: C1/C2/C4 acceptance arms pass, 64 generated segments with zero corruption,
24/24 main QSA and 2/2 MTP draft scales loaded under strict checking.
KV capacity (engine-reported, same image both arms): FP16 433,401 → E4M3 775,096
tokens, +78.8%.
Throughput, single-variable: identical image, weights, draft, offload spec, gmu,
max_num_seqs,max_model_len, compilation config and seed; the only difference iskv_cache_dtypefor main and draft. Prompts are cut from this repository's ownbenchmarks/sonnet.txtplusdocs/*.md, each request carries a unique nonce so nothing isserved from the prefix cache (
prefix_cache_hit_blocksis 0 on every run), 3 repeats,medians:
The decode cost is disclosed, not hidden. It is not a constant tax: step time is
essentially unchanged (p50 +0.8–1.4%, p90 +0.7–1.6%), so attention itself is not slower.
The decode delta tracks tokens-per-step, which tracks MTP draft acceptance. At 1k both arms
show identical acceptance (0.582) and decode is within noise; the gap grows with context,
which is what KV quantisation error accumulating along the sequence looks like.
Workload note: MTP acceptance was measured per request and targeted to the 63% ± 3% seen on
real agent traffic on this deployment (measured medians 0.58–0.76). Synthetic prompts are
unusable for this comparison — they pin tokens-per-step near the MTP3 ceiling of 4.0, which
erases the very variable the decode cost flows through.
Not caused by this change
This stack was investigated for an unrelated non-terminating thinking loop on AIME 2026.
A single-variable FP16 control reproduces the loop at essentially the same offset
(reasoning char 731 vs 738, same repeating unit), it also reproduces with speculative
decoding disabled entirely and on an older build, and it does not occur at all under the
model card's recommended thinking-mode sampling (0/20 trajectories). E4M3 KV is not
implicated. Separately, the temperature>0 output corruption seen at
max_num_seqs>2isthe pre-existing
draft_sample_method=probabilisticdefect in #656, reproducible on FP16 KV.Re-validation on current main
On main
1e90d17f2cwith this PR, 4×V100 TP4, E4M3 KV, MTP3, CUDA graphs, prefix caching and 32 GiB grouped CPU offload, fresh servers:Known limitations
draft_sample_methodmust begreedyabovemax_num_seqs=2until [Bug][Spec Decode] probabilistic draft sampling corrupts output above max_num_seqs=2 at temperature > 0 #656 is resolved.Co-authored-by: areslp 100579+areslp@users.noreply.github.com
🤖 Generated with Claude Code