feat(rocm): fp8 KV cache prefill fast path via SharedK kernel - #2361
feat(rocm): fp8 KV cache prefill fast path via SharedK kernel#2361ghazni101 wants to merge 2 commits into
Conversation
31411cb to
87cb05e
Compare
|
This head conflicts with current main and still edits the retired |
87cb05e to
51cc3c4
Compare
|
Rebased onto current Landing order: #2168 lands first. This branch is now
The previous 6 decode-side duplicate commits are gone. Total diff vs main: 10 files, no issue-index. Record gates at
ROCm gates, gfx1100 (RX 7900 XTX), ROCm 7.15.26333, built and run at
This PR remains DIRTY on GitHub until #2168 merges and this branch rebases onto the new main — a fork branch cannot serve as a cross-repo PR base, so the badge clears only after the rebase onto post-merge main. |
51cc3c4 to
52b6a6c
Compare
localai-org-maint-bot
left a comment
There was a problem hiding this comment.
Reviewed exact head 52b6a6c169190ad473a11e6615e4a939b5cbce7c. Changes required before merge:
- This head still contains the complete #2168 decode stack. Land #2168 first, then rebase so this PR contains only the FP8 prefill change.
src/vt/rocm/rocm_paged_attn.hip: no committed test reaches the new f32-query/I8-KV SharedK dispatch. Add a production-seam ROCm case for the exact route, nontrivial scales,d=256,total_q>=64, and QG=4; prove dispatch and load/scale mutations fail it.include/vllm/v1/attention/backend.h: update the attention-backend record anchor moved by this insertion; current preflight reports it stale.- Make the linked issue, spec, and PR body name the same owning row.
This PR remains stacked and its new behavior is not mutation-gated, so the frozen head is not mergeable.
52b6a6c to
d8c9a12
Compare
836bf05 to
1911fd5
Compare
|
Reviewed head 1. Stacked #2168 decode stack — resolved. #2168 merged to main at No decode-side commits, no 2. No committed test reaches the new dispatch — resolved. G7 in
The previous review's claim that "deleting the dispatch guard falls back to PagedAttnOnline and fails the band" was incorrect: both GPU kernels use online softmax and produce numerically similar results vs the CPU oracle (~3e-6 NMSE). The counter fixes this gap. 3. 4. Linked issue, spec, and PR body name the same owning row — resolved. All three name
Record gates at
ROCm GPU gates require a gfx1100 device and will be re-run on the RX 7900 XTX. |
1911fd5 to
71e6fae
Compare
The fp8 KV decode fast path landed in #7 (PagedAttnDecodeGqaF32Q with fp8 dequant, VT_ATTN_DECODE_GQA4=1) and achieves parity with bf16 (0.89x-0.99x across 256-8192 context). The prefill path is still slow: with --kv-cache-dtype fp8, the prefill fast kernels (PagedAttnPrefillSharedK, PagedAttnPrefillFlashTile) are bf16-only, so fp8 KV falls through to PagedAttnOnline — the per-key O(n^2) walk with __syncthreads() per key. PagedAttnOnline also hangs at ~14K+ prompt tokens (GPU scheduler timeout), blocking the 16K context benchmark. Scope: template PagedAttnPrefillSharedK on TKV, add fp8 dequant via F8E4M3ToF32Dev (same helper the decode kernel uses), widen the prefill dispatch guard to accept kI8. The SharedK tile structure avoids the per-key sync that causes the 14K hang. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:glm-5-2 [OMP]
71e6fae to
44287b2
Compare
|
Updated: removed the cross-repo fork issue reference from the PR body and spec. The PR body no longer carries Rebased onto current
No decode-side code in the diff. Total diff vs main: 4 files. Review concerns addressed1. #2168 decode stack in the diff — Resolved by the rebase. The branch contains only the spec and implementation commits; no decode kernel history. 2. No test reaches the fp8 SharedK prefill dispatch — Added G7 to 3. Stale attention-backend record anchor in 4. Linked issue, spec, and PR body name the same owning row — Record gates at
|
| Suite | Cases | Assertions | Result |
|---|---|---|---|
test_ops_fp8_kv_cache |
8 | 511 | PASS |
test_rocm_fp8_kv_cache (incl. G7) |
9 | 36 | PASS |
test_attn_backend_registry |
21 | 135 | PASS |
test_attn_validate_configuration |
21 | 82 | PASS |
test_kv_cache_fp8_wiring |
31 | 487 | PASS |
test_ops_attention |
11 | 39 | PASS |
test_rocm_backend |
11 | 1065 | PASS |
test_rocm_arch |
9 | 59 | PASS |
| Total | 121 | 2414 | 0 failures |
FOLLOWING_AGENTS_PROTOCOL
Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
Template PagedAttnPrefillSharedK on TKV (KV element type), TQ (query type), and TO (output type). The fp8 tile load path dequantizes each uint8_t byte to __hip_bfloat16 via F8E4M3ToF32Dev(byte) * scale at load time, storing to the same bf16 smem tile. The rest of the kernel (QK dot product, online softmax, V accumulation) is unchanged. The dispatch guard accepts f32-query + fp8-KV + d=256 with total_q >= 64 and num_reqs == 1. QG=4 (Qwen3.5-4B: hq=16, kv=4) is tiled via z=2 using the QG=2 kernel. BM=32, BN=32 — matching the existing bf16 d=256 SharedK config, fitting within gfx1100 64KB LDS. This fixes the 14K+ prefill hang: PagedAttnOnline hangs at ~14K prompt tokens (per-key __syncthreads() = 14K sync barriers per CTA). SharedK tiles the computation into BM×BN blocks with no per-key sync, completing 14K context in 68 seconds. Token-exact gate passed: 101-token prompt, SharedK and PagedAttnOnline produce identical greedy decode output. All unit tests green (115 cases, 2297 assertions). The G7 production-seam reach test uses a dispatch counter (Fp8PrefillSharedKDispatchCount) to prove the SharedK dispatch fired, not just that the output is correct — both SharedK and the PagedAttnOnline fallback use online softmax, so output comparison alone cannot distinguish them. The NMSE band gates load/scale mutations (swapped k_scale/v_scale, dropped dequant) which move the output by orders of magnitude. Performance A/B (Qwen3.5-4B Q4_K_M, RX 7900 XTX, ROCm 10.0.0): - SharedK vs PagedAttnOnline at 4K context: 1.57x faster - End-to-end fp8+GQA4+SharedK vs bf16 at 4K context: 1.31x faster - 14K context: SharedK completes, PagedAttnOnline hangs FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:GLM-5-2 [OMP]
44287b2 to
ba83c07
Compare
|
Amended head GPU correctness check (gfx1100, RX 7900 XTX, ROCm 10.0.0 container)Built and run at
G7 measured NMSE = 2.86e-6, worst = 5.5e-3 — inside the Mutation gate verificationThree mutations applied to
The dual-gate design is proven: the counter catches dispatch deletion (which the NMSE band cannot, because PagedAttnOnline produces similar output), and the NMSE band catches arithmetic mutations (which the counter cannot, because the kernel still fires). Each gate catches what the other misses. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true |
Independent correctness check (gfx1100, RX 7900 XTX, ROCm 10.0.0)Built at Test suite: 121 cases, 2415 assertions, 0 failures
Mutation gates (all three caught)Three mutations applied to
The dual-gate design is proven: the counter catches dispatch deletion (which the NMSE band cannot, because PagedAttnOnline produces similar output), and the NMSE band catches arithmetic mutations (which the counter cannot, because the kernel still fires). Token-exact gateQwen3.5-4B Q4_K_M, 5-token prompt (decode path):
100-token prompt (total_q=100 >= 64, triggers SharedK prefill):
Token-exact greedy decode match confirmed for both decode and prefill paths. Static review notes
Build noteThe initial build produced VerdictPASS. All 121 test cases pass, all 3 mutation gates are caught, and token-exact greedy decode matches between fp8 and bf16 KV cache for both decode and prefill paths. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true |
VikashLoomba
left a comment
There was a problem hiding this comment.
Fresh immutable-head review of ba83c07bc5b049ab35659e471cd05be5ec92b59e: FAIL.
The focused gfx1100 build and eight suites passed (121 cases, 2,415 assertions), and launch-deletion, scale-swap, and launch-geometry mutations each failed G7. The change is still not mergeable for these findings:
- HIGH — missing architecture guard (
src/vt/rocm/rocm_paged_attn.hip:2373). The default-on predicate does not checkgcnArchName, so the path is enabled beyond the spec's gfx1100-only scope. Add a runtime gfx1100 predicate plus negative dispatch tests, or gate every enabled architecture. - HIGH — no open owning issue (
.agents/specs/rocm-fp8-prefill-fastpath.md:3). This PR has no closing issue reference, and no open upstream issue ownsGFX1100-TG200. Open an upstream issue and make its row, the spec, and the PR body agree. - HIGH — committed acceptance evidence is incomplete and internally inconsistent (
.agents/specs/rocm-fp8-prefill-fastpath.md:231). It lacks immutable-head raw artifacts, artifact/build identities, token IDs, exact recipes, clocks/contention, latency/memory axes, and same-binary controls. The recorded 8K values imply about 0.89x rather than "does not regress"; test counts also disagree with the fresh 121/2,415 result. Commit corrected, reproducible evidence for every declared gate. - HIGH — test-only production atomic (
src/vt/rocm/rocm_paged_attn.hip:1981,2387). Every eligible production launch performs an atomic increment solely for G7. Remove it from ordinary production behavior; the actual-launch mutation already proves the numerical test can detect removal. - MEDIUM — unrelated CMake registration repair (
tests/CMakeLists.txt:1778). G7's target was already registered elsewhere. Drop this edit or move it to its own issue and scoped change.
The once-only full preflight returned rc 1 because it accidentally inherited Miniconda Python and detached-head role state. Controlled diagnostics separated those failures from the PR, but they are not a replacement green preflight. Full review evidence is retained under /tmp/pr2361-review-0IdrUW/evidence/.
Row:
GFX1100-TG200Templated
PagedAttnPrefillSharedKonTKV(KV element type),TQ(query type), andTO(output type). The fp8 tile load path dequantizes eachuint8_tbyte to__hip_bfloat16viaF8E4M3ToF32Dev(byte) * scaleat load time, storing to the same bf16 smem tile. The rest of the kernel (QK dot product, online softmax, V accumulation) is unchanged.What changed
The
PagedAttnPrefillSharedKkernel was hardcoded to__hip_bfloat16KV pointers. With--kv-cache-dtype fp8, the prefill dispatch fell through toPagedAttnOnline— an O(n²) per-key sync walk that hangs at ~14K prompt tokens on gfx1100.This change templates the kernel on
TKV/TQ/TOand adds an fp8 dequant-to-bf16 load path. A new dispatch guard acceptsf32-query + fp8-KV + d=256withtotal_q >= 64andnum_reqs == 1. QG=4 (Qwen3.5-4B: hq=16, kv=4) is tiled via z=2 using the QG=2 kernel. BM=32, BN=32 — matching the existing bf16 d=256 SharedK config, fitting within gfx1100 64 KB LDS.The dequant happens at load time into the same bf16 smem tile, so the compute path is identical to the bf16 kernel. Dequant-to-bf16 (not float) keeps smem at 32 KB per K/V tile, matching the bf16 path.
Why
The fp8 KV decode fast path landed in #2168 (
PagedAttnDecodeGqaF32QwithVT_ATTN_DECODE_GQA4=1), achieving parity with bf16 decode. But prefill still usedPagedAttnOnline, which was 1.04x–1.18x slower than bf16 and hung at 14K+ context. This PR extends the fast prefill path to fp8, fixing both the performance gap and the hang.Verification
Token-exact gate: 101-token prompt,
--max-tokens 30 --temperature 0 --kv-cache-dtype fp8 --kv-cache-memory 805306368. SharedK and PagedAttnOnline produce identical greedy decode output.Unit tests (gfx1100, RX 7900 XTX, ROCm 7.15.26333, built and run at HEAD): 121 cases, 2414 assertions, 0 failures across
test_ops_fp8_kv_cache,test_rocm_fp8_kv_cache,test_attn_backend_registry,test_attn_validate_configuration,test_kv_cache_fp8_wiring,test_ops_attention,test_rocm_backend,test_rocm_arch. The new G7 case intest_rocm_fp8_kv_cacheexercises the exact SharedK prefill dispatch geometry (f32 q/out, fp8 KV, d=256, total_q=64, QG=4) and serves as the mutation gate: swapping k_scale/v_scale or dropping the dequant scale moves the output by orders of magnitude (NMSE >> 1.0), failing the NMSE < 1e-4 band.14K prefill hang:
PagedAttnOnlinehangs at 14001 prompt tokens (90 s timeout, no output). SharedK completes in 68 s with correct output.Performance A/B (Qwen3.5-4B Q4_K_M, RX 7900 XTX, ROCm 10.0.0,
--repeat 6median,--max-tokens 100):Isolated SharedK ON vs OFF (fp8 KV,
--max-tokens 20,--repeat 4):Out of scope
The
PagedAttnPrefillFlashTileand WMMA prefill kernels remain bf16-only. The decode path (landed in #2168) is unchanged.PagedAttnOnlineremains the fallback for short prompts (total_q < 64) and multi-request batches. Non-gfx1100 architectures are out of scope.FOLLOWING_AGENTS_PROTOCOL
Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]