Repository navigation
feat(vllm): support 0.28 packed attention KV storage - #493
Merged
RixinLiu merged 2 commits intoSep 24, 2026
Merged
Conversation
This was referenced Sep 15, 2026
Closed
shipiyouniao
force-pushed
the
feature/vllm-028-packed-kv
branch
from
September 21, 2026 13:42
1746096 to
3235b73
Compare
This was referenced Sep 22, 2026
shipiyouniao
force-pushed
the
feature/vllm-028-packed-kv
branch
from
September 24, 2026 19:50
3235b73 to
5b74b3a
Compare
RixinLiu
self-requested a review
September 24, 2026 21:15
Collaborator
|
Added FlashAttention 2 coverage on A100. On vLLM 0.28 at 5b74b3a, both KVCached layouts matched native on all 48 complete outputs per layout. Setup: Qwen2.5-0.5B-Instruct BF16, CUDA graphs and APC enabled. I also reproduced a startup failure on vLLM 0.27: the backend returns packed KV, but the |
This was referenced Sep 25, 2026
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.
Summary
Part of #490 (packed KV storage). #492 has merged as
055f05569a8a23f930a4de3ff0204a60ecd82142; this PR is now one packed-storage commit directly on that main revision. It no longer carries the profiling change, whose affected contract starts at vLLM 0.27+. #500 and #494 are separate children of this storage step.vLLM 0.28 CUDA attention backends expose a four-dimensional
(blocks, heads, tokens, K+V)cache instead of the five-dimensional layout with a separate K/V axis. The old adapter rejects that shape during graph-profiler temporary-cache initialization.This change allocates one combined K/V backing pool per layer and builds views using the backend's stride order. It handles NHD and HND, contiguous and non-contiguous layer storage, and differing logical/kernel block sizes. EngineCore and worker use the same physical block geometry. Unsupported layouts and padded page geometries are rejected before an incompatible view is used; padded-page support remains tracked by #426.
Capability discovery includes HND for packed K/V, while legacy split K/V remains NHD-only. An unimplemented backend stride-order method means logical order, matching vLLM's contract. The rebase preserves main's cross-layer-sharing, heterogeneous-view and lifecycle changes.
The packed engine geometry is CUDA-scoped. ROCm retains its existing split-KV path because
ROCM_ATTNstill uses a five-dimensional cache on 0.28. Packed ROCm backends remain explicitly unsupported rather than assigning incompatible engine/worker geometry; this PR does not claim AMD runtime validation.The native vLLM 0.28 Triton scale-cache implementation already respects tensor strides and storage offsets. The older five-dimensional KVCached override is therefore not installed on that version.
Storage and View Construction
The worker's _build_packed_kv_views() constructs a view, not a copy or a second K/V allocation. Shape alone is insufficient: NHD and HND expose the same four axes but use different inner strides.
The allocation path selects unified storage for packed K/V and passes the matching buffer count to the native allocator. A logical block split into smaller kernel blocks changes the view's block count and stride, not the scheduler's block-ID contract.
Before
sequenceDiagram participant R as V1 runner or graph profiler participant B as Attention backend participant A as KVCached adapter R->>B: Get cache shape B-->>R: Four-dimensional packed K/V R->>A: Allocate cache A->>A: Apply legacy explicit-K/V-axis validation A-->>R: Unsupported shapeAfter
sequenceDiagram participant R as V1 runner or graph profiler participant B as Attention backend participant A as KVCached adapter participant F as Virtual backing storage R->>B: Get shape and layout B-->>R: Packed dimensions and NHD or HND R->>A: Allocate using logical and kernel block sizes A->>A: Validate supported geometry A->>F: Create unified K/V backing A->>A: Build per-layer strided views A-->>R: Backend-compatible views Note over A,F: Physical pages remain demand-mappedFor contiguous layer storage, the block stride includes all layers and each view has its own layer offset. For non-contiguous storage, each layer has separate backing. Padding and unsupported layouts fail validation; the diagram is not a claim that every four-dimensional backend format is supported.
Validation
Tested commit:
5b74b3a0f6b12943a0c8fe4b38b9579d3568e782.The functional prompts covered a fixed reply, simple arithmetic, a factual question, and Chinese text. Full responses and token counts were checked, not just HTTP status.
A second native run also completed all 16 requests. Concurrent long outputs matched the first native run in 15/16 cases for both KVCached layouts and for the second native run itself. This is not a bitwise-equivalence claim for concurrent generation; the fixed functional responses remained identical across all runs.
No startup/serving CUDA error, illegal access or EngineCore failure was observed. Shutdown is not signed off by this layout test: the native and patched runs logged forced EngineCore termination and resource-tracker warnings, and one patched run logged an output-handler
EngineDeadErrorafter shutdown had begun. These are retained in the evidence rather than reported as a completely clean lifecycle run. The GPU returned to idle and the test container did not restart.All eight real CUDA VMM probes passed, covering both layer layouts, NHD/HND, and logical/kernel block-size ratios 1 and 2. Each probe maps 600 blocks across physical-page boundaries, writes and checks distinct K/V values for three layers, releases the pages, forces a physical-headroom rejection using an actual CUDA allocation, releases that pressure, and verifies all 600 blocks can be allocated and used again. After the external CUDA allocation is freed, the probe allows bounded retries for main's 100 ms physical-capacity cache; every case recovered after five 20 ms retries. The original immediate-recovery assertion no longer matches that merged cache contract. Its initial failure is retained separately and is not counted as a passing run.
The native C++ source tree, build definition and Python VMM binding are identical to the already-built validation binary. That binary was reused and its import verified against this checkout. The Python adapter, CPU matrix and real-device probes above were rerun on the exact head. A dedicated local Codex review completed with no remaining actionable findings.
Scope
This is a V1 packed-storage step, not complete vLLM 0.28 support. HND view correctness is tested independently; full-model serving here covers Triton NHD only. FlashAttention/FlashInfer serving, ROCm packed storage, quantized/padded layouts, V2, hybrid prefix-cache lifecycle, and distributed failure ordering still need their own validation. These single-GPU results do not establish TP/MPS correctness or a performance comparison.