feat(KV-FP8): W6 — the ROCm fp8-e4m3 KV cache store and read - #2080
Merged
Conversation
Append the W6 section to the fp8-kv-cache spec: scope, upstream chain, port map, gates, and the wave-table row. The ROCm arm mirrors the W2 CUDA arm elementwise, with the CPU kernels (W1) as the oracle. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:glm-5-2 [OMP]
The ROCm backend gains the fp8-e4m3 KV cache store kernel and the fp8 dequant on the paged-attention read, closing the last non-Metal gap in the fp8 KV cache surface. The store kernel mirrors the W1 CPU codec and the W2 CUDA arm elementwise; the read dequant multiplies back by the per-tensor k_scale/v_scale. ROCm HIP has no __nv_cvt_float_to_fp8 intrinsic, so the store uses a software codec (F32ToF8E4M3Dev) with frexpf/nearbyintf/ldexpf arithmetic that mirrors the CPU vt::F32ToF8E4M3. The codec is bit-identical and portable across all ROCm targets, unlike hardware fp8 conversion intrinsics that exist only on CDNA2+ (gfx940/941/942). OpId::kReshapeAndCacheFp8 is registered for DeviceType::kROCM in rocm_ops.hip. The fp8 read refusal in ops.cpp widens from kCPU||kCUDA to kCPU||kCUDA||kROCM. Metal remains refused by name. Gated on gfx1100 (RX 7900 XTX): test_rocm_fp8_kv_cache 7/7 cases, 28/28 assertions. G3 store is byte-identical to the W1 CPU oracle; G4 f32 read NMSE < 1e-6; G4b bf16 read NMSE < 1e-4; G5 e5m2 refused with the named message. RED-first proven: dropping *scale in the read dequant fails G4/G4b at NMSE ~34000x; dropping /scale in the store fails G3 at the byte level. Existing suites unaffected: test_rocm_backend 9/9, test_ops_paged_attn 14/14, test_ops_fp8_kv_cache 8/8. Closes mudler#2065 FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:glm-5-2 [OMP]
ghazni101
force-pushed
the
row/KV-FP8-ROCM
branch
from
August 27, 2026 10:18
80a0f19 to
872b53e
Compare
ghazni101
marked this pull request as draft
August 27, 2026 18:08
ghazni101
marked this pull request as ready for review
August 28, 2026 00:07
GitHub reported mudler#2080 DIRTY against mudler/vllm.cpp main. This merges upstream/main 5e9d81d (127 commits past the branch base 3e4cd6d) into the row branch so the pull request is mergeable again. The overlap since the base is confined to seven files, and none of them needed a hand resolve: the four record matrices are row-disjoint (this row edits BACKEND-ROCM, KV-FP8, and QUANT-KV-FP8; upstream touched other rows plus the count table), the issue index is an append-only union (846 ids = 714 base + 1 here + 131 upstream, nothing missing from either side, mudler#2065 present exactly once), the ops.h change here is a comment reword only (the enum values all came from base and upstream, so no op id shifted), the ops.cpp fp8 read refusal still admits kROCM at the widened guard, and tests/CMakeLists.txt keeps exactly one test_rocm_fp8_kv_cache registration beside upstream's additions. The .hip files and the spec were untouched by upstream since the base, so the ROCm kernels carry over byte-identical. Re-gated on the local gfx1100 (RX 7900 XTX) in a ROCm 10.0.0 container, file mutex held: test_rocm_fp8_kv_cache 7/7 cases 28/28 assertions, test_rocm_backend 9/9 1065, test_ops_paged_attn 15/15 1838 (upstream added one case since the branch point), test_ops_fp8_kv_cache 8/8 511, test_ops_paged_attn_dtype 3/3 172, and test_ops_paged_attn_sharedk_wmma_p1 7/7 32813. The assertion counts match the pull request's recorded gate. check-agent-record.py and check-conflict-markers.py pass on the merged tree. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:glm-5.3 [OMP]
Collaborator
|
@mudler This ROCm fp8-KV arm is ready for CI review, but the current reconciled head has no checks because its workflows still need approval. The branch includes focused byte-identity, dequantization, refusal, and backend regression tests with gfx1100 evidence. Please approve the current-head workflows before a merge decision. |
This was referenced Aug 28, 2026
Closed
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.
What changed
The ROCm backend gains the fp8-e4m3 KV cache store kernel
(
ReshapeAndCacheFp8KernelRocminsrc/vt/rocm/rocm_dense_basic.hip) andthe fp8 dequant on the paged-attention read (
LoadKvinsrc/vt/rocm/rocm_paged_attn.hip). This closes the last non-Metal gap inthe fp8 KV cache surface.
OpId::kReshapeAndCacheFp8is registered forDeviceType::kROCMinsrc/vt/rocm/rocm_ops.hip. The fp8 read refusal insrc/vt/ops.cppwidens from
kCPU || kCUDAtokCPU || kCUDA || kROCM. Metal remainsrefused by name.
ROCm HIP has no
__nv_cvt_float_to_fp8intrinsic, so the store uses asoftware codec (
F32ToF8E4M3Dev) withfrexpf/nearbyintf/ldexpfarithmetic that mirrors the CPU
vt::F32ToF8E4M3. The codec isbit-identical and portable across all ROCm targets, unlike hardware fp8
conversion intrinsics that exist only on CDNA2+ (gfx940/941/942).
Why
The fp8 KV cache halves the KV footprint. The CPU arm (W1) and CUDA arm
(W2) already landed; the ROCm arm was the last refused backend. Issue
#2065 tracks this work.
How to verify
Build with HIP and run the test:
Measured on gfx1100 (RX 7900 XTX), hipcc 7.2.4:
test_rocm_fp8_kv_cache: 7/7 cases, 28/28 assertions. G3 storebyte-identical to the W1 CPU oracle; G4 f32 read NMSE < 1e-6; G4b bf16
read NMSE < 1e-4; G5 e5m2 refused with the named message.
test_ops_fp8_kv_cache: 8/8, 511 assertions (CPU regression).test_rocm_backend: 9/9, 1065 assertions (no regression).test_ops_paged_attn: 14/14, 1646 assertions (no regression).RED-first proven: dropping
*scalein the read dequant fails G4/G4b atNMSE ~34000x; dropping
/scalein the store fails G3 at the byte level.Out of scope
fp8_e5m2 compute, per-attention-head scales, the Metal arm, fast-path
(tensor-core/rocWMMA) fp8 attention kernels, and the memory-halving e2e
measurement on a ROCm gate model.
Relationship with #1936 and landing order
#1936 (the GFX1100-TG200 campaign) cherry-picked this PR's W6 store
and read work (commit
87c6f2518516) so its fp8 decode attention armcan be tested end-to-end. The decode read side in #1936 (commit
e43a39d45803) depends on this store side -- both are needed for fp8KV cache to work.
Landing order:
KV-FP8 W6: the ROCm fp8-e4m3 KV cache store and read #2065.
87c6f2518516since the store work is then in main.All 13 files in this PR are currently also in #1936. After this PR
lands and #1936 rebases, the overlap is zero.
Closes #2065
FOLLOWING_AGENTS_PROTOCOL
Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:glm-5-2 [OMP]