Skip to content

feat(rocm): f32-query decode GQA kernel with bf16 and fp8 KV cache support - #2168

Merged
mudler merged 10 commits into
mudler:mainfrom
ghazni101:row/fp8-kv-decode-attn
Sep 2, 2026
Merged

feat(rocm): f32-query decode GQA kernel with bf16 and fp8 KV cache support#2168
mudler merged 10 commits into
mudler:mainfrom
ghazni101:row/fp8-kv-decode-attn

Conversation

@ghazni101

@ghazni101 ghazni101 commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Row: GFX1100-TG200

What changed

Add PagedAttnDecodeGqaF32Q — a warp-strided decode attention kernel for
the f32-query x bf16/fp8-KV x f32-output dtype combination that the GGUF
dense path uses. Without this arm, f32-query decode falls through to
PagedAttnOnline, which walks each context token with a per-key
__syncthreads() reduction (~593us/call, 8 calls/token on Qwen3.5-4B).

The kernel fuses QG=4 query heads per KV group, walks the sequence
warp-strided, and does register online softmax with no per-key block
sync. EPL = d/32 (8 at d=256, 4 at d=128). Dispatch is gated behind
VT_ATTN_DECODE_GQA4=1 for the exact geometry (f32 q/out, bf16 or fp8
k/v, d=128 or 256, hq=16, kv=4).

fp8 KV cache support

--kv-cache-dtype fp8 set the KV cache to DType::kI8, which failed
the kBF16 guard on every optimized decode kernel in
rocm_paged_attn.hip. The dispatch fell through to PagedAttnOnline
— the reference kernel with per-key __syncthreads reduction, no GQA
amortization, no vectorized loads. Up to 7.5x decode regression at long
context on gfx1100.

Fix: template PagedAttnDecodeGqaF32Q on TKV (default
__hip_bfloat16) with k_scale/v_scale params. Add
LoadRowEplFp8<EPL> (vectorized uint8_t loads + F8E4M3ToF32Dev
dequant x scale) and LoadRowEplKv<EPL, TKV> (if constexpr dispatch
between bf16 and fp8). Widen the dispatch guard:
kBF16 || (kI8 && kv_cache_dtype != kAuto).

The dequant arithmetic is identical to the existing LoadKv(uint8_t *, ...) at line 176 — the fast kernel now calls the same dequant the
fallback already used.

Benchmark

Qwen3.5-4B Q4_K_M, RX 7900 XTX, ROCm 7.14.0, 128-token greedy decode,
4 reps:

Context Before (tok/s) After (tok/s) Speedup vs bf16 KV
256 99.94 140.19 1.40x 98%
1024 56.28 122.31 2.17x 95%
4096 20.53 79.53 3.87x 86%
8192 11.08 54.55 4.93x 82%
16384 5.78 33.47 5.79x 78%

Correctness

3/3 simple prompts produce token-exact identical output vs the
PagedAttnOnline fallback. Divergence at thinking-tag near-ties is the
reduction-order risk the bf16 GQA4 path already carries — same policy
class as VT_ATTN_DECODE_D128. The arm ships opt-in
(VT_ATTN_DECODE_GQA4=1); near-tie adjudication before any default-ON
flip remains owed.

Relationship with #2080 and #1936

This PR is the fp8 decode-attention split from #1936, per the reviewer's
request. #1936 carried two units of work: the GFX1100-TG200 decode
campaign and this fp8 KV decode-attention arm. This PR contains only the
fp8 arm.

This PR builds on the ROCm fp8-e4m3 KV cache store and read that landed
in #2080 (191f64608). The store side is on main; this PR adds the
decode-attention read side. The 08595f335 fix (#2161) for the G1b
test predicate is also in the base.

The TG200 campaign remains on #1936 and will be sent separately after
this lands.

How to verify

cmake -B /tmp/build -DVLLM_CPP_HIP=ON
make -j4 vllm test_rocm_fp8_kv_cache test_attn_backend_registry test_capi vllm-cli test_cli_kv_cache_dtype
ctest -R 'rocm_fp8|attn_backend|capi|cli_kv_cache'

Verified on gfx1100 (RX 7900 XTX), ROCm 7.14.0:

  • test_rocm_fp8_kv_cache: 8/8 cases, 32 assertions (G6 exact-geometry reach test passes on GPU)
  • test_attn_backend_registry: 21/21 cases, 135 assertions (ROCM_ATTN FP8 cache config acceptance)
  • test_capi: 68/68 cases, 676 assertions (ABI v24 kv_cache_dtype default + acceptance)
  • test_cli_kv_cache_dtype: 2/2 cases, 12 assertions (--kv-cache-dtype reaches the loader)
  • test_rocm_backend: 9/9 cases, 1065 assertions
  • test_ops_quant_dot: 28/28 cases, 210138 assertions

Review-driven updates (review 5070827757)

  1. G6 exact-geometry reach testtest_rocm_fp8_kv_cache.cpp G6 uses
    hq=16, kv=4, d=128, f32 q/out, fp8 KV — the exact GQA4 guard geometry.
    G4/G4b (hq=2, H=1, D=16) never reaches the dispatch; G6 does.
  2. C ABI + vllm-cli end-to-end gatetest_capi.cpp v24
    kv_cache_dtype default-NULL and acceptance; test_cli_kv_cache_dtype.cpp
    --kv-cache-dtype reaches the loader.
  3. ROCM_ATTN FP8 cache config acceptancetest_attn_backend_registry.cpp
    asserts supported_kv_cache_dtypes includes fp8/fp8_e4m3 and
    supports_kv_cache_dtype binds the declaration to selection.
  4. Public C-ABI/FP8 docsUSAGE.md and FEATURES.md updated for
    ABI v24 kv_cache_dtype field.
  5. Spec before implementation — commit b8a859e1e (spec) precedes
    7bc79e87b (implementation).
  6. One owning row — issue docs(metrics): spike Prometheus parity surface #7, spec, and PR body all reference
    GFX1100-TG200.

Out of scope

fp8_e5m2 compute, per-attention-head scales, the Metal arm, fast-path
(tensor-core/rocWMMA) fp8 attention kernels, the bf16 decode-opt
kernels, the prefill fp8 path, non-gfx1100 architectures.

Spec: .agents/specs/rocm-fp8-kv-decode-attn.md
Evidence: docs/bench-evidence/gfx1100-tg200-t3a-20260823.md
Tracking issue: ghazni101#7

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]

@localai-org-maint-bot

Copy link
Copy Markdown
Collaborator

The split from #1936 is clear and the fp8 read-side dispatch is appropriately opt-in, but this head now conflicts with current main. Please rebase it and rerun the ROCm fp8 KV-cache/backend gates plus the branch record checks before merge.

@ghazni101
ghazni101 force-pushed the row/fp8-kv-decode-attn branch from 74510c5 to a05d760 Compare August 29, 2026 13:28
@ghazni101

Copy link
Copy Markdown
Contributor Author

Done — rebased onto current main and every gate rerun.

Integration. The branch is now a linear chain on main at c3522bc7d; the two merge(fp8-kv-decode-attn) integration commits are gone, which resolves the DIRTY state at the source. Head a05d760f7:

  • b37718f96 feat(rocm): f32-query decode GQA kernel with bf16 and fp8 KV cache support
  • aa8bddb74 feat(rocm): advertise fp8 and fp8_e4m3 on RocmAttentionBackend (message trailers repaired)
  • 7243aafac record(GFX1100-TG200): escape the row's guard pipes, advance the MLA anchor (new)
  • a05d760f7 docs(ENVIRONMENT): document VT_ATTN_DECODE_GQA4 (new)

Branch record checks. The ratchet activated by the integration found two regressions this PR owns, both repaired:

  • The GFX1100-TG200 row quoted the widened guard as kBF16 || kI8 with unescaped pipes inside a code span, so the table-shape gate counted 7 pipes against the table's 5. Now \|\|.
  • The supported_kv_cache_dtypes insertion in include/vllm/v1/attention/backend.h moved get_kv_cache_shape from :580 to :587, taking the KERNEL-ATTN-MLA-SPARSE citation one past the ratchet's baseline (29 stale against 28). The citation is advanced to :587; the baseline is untouched.

scripts/check-agent-record.py: ENGINE=173 MODEL=379 QUANT=85 KERNEL=58 BACKEND=87 ANCHOR-ROT=33.

One gate the branch newly owed. check-env-doc reads std::getenv("VT_ATTN_DECODE_GQA4") in src/vt/rocm/rocm_paged_attn.hip, and the knob sat on neither documentation surface. It is a behavior-changing dispatch gate rather than a kernel-internal tuning switch, so it is now documented in docs/ENVIRONMENT.md with its geometry, default, and the near-tie caveat, instead of being allowlisted.

ROCm gates, gfx1100 / RX 7900 XTX, ROCm 7.14.0, built and run at a05d760f7 (under the box GPU mutex):

  • test_rocm_fp8_kv_cache: 7/7 cases, 28 assertions
  • test_rocm_backend: 9/9 cases, 1065 assertions

Checks. scripts/agent-preflight.sh: all gates green. One honest limit on scripts/agent-ready.py: it reports REMOTE_UNVERIFIED on its remote-base sub-check because the installed gh does not know the baseRefOid JSON field. The base was verified instead with git fetch upstream + git rev-parse at c3522bc7d immediately before the push, and the head update went out as a --force-with-lease pinned to the pre-rebase head 74510c5df. main was never rewritten; the rewrite is confined to this fork-published row/* head.

@ghazni101

Copy link
Copy Markdown
Contributor Author

Rebased onto current main at 5ab4493c0. Head c24c2b715, 6 commits, linear chain — no merge commits, no DIRTY state.

The retired .agents/issue-index.md edits are dropped. The file moved to .agents/completed/issue-index.md on main at 7dc2ef1ea; our row additions to it are removed, and the branch diff no longer touches either path.

Landing order: this PR (#2168) lands first. #2361 (fp8 prefill fast path) builds on this branch and shares the decode kernel history. It has been slimmed to only its 2 prefill-specific commits rebased onto this head, so the decode kernel history lands exactly once.

Record gates at c24c2b715:

  • check-agent-record: OK (ENGINE=173 MODEL=379 QUANT=85 KERNEL=58 BACKEND=87 ANCHOR-ROT=33)
  • check-commit-style: OK
  • test_check_commit_trailers: 64 tests, OK

ROCm gates, gfx1100 (RX 7900 XTX), ROCm 7.15.26333, built and run at c24c2b715 (under ${GPU_LOCK}):

  • test_rocm_fp8_kv_cache: 7/7 cases, 28 assertions — passed
  • test_rocm_backend: 9/9 cases, 1065 assertions — passed

@ghazni101
ghazni101 force-pushed the row/fp8-kv-decode-attn branch from c24c2b7 to 934ff06 Compare August 31, 2026 12:50

@localai-org-maint-bot localai-org-maint-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed exact head 934ff06e278178ae056ac94fbef282e2ef25a937. Changes required before merge:

  • src/vt/rocm/rocm_paged_attn.hip: add an exact-geometry ROCm test that reaches the GQA4 FP8 kernel. Existing FP8 coverage uses hq=2, d=16, and never enables this route, so deleting the dispatch remains green.
  • Gate the new C ABI and vllm-cli path end to end, not only direct kernel calls.
  • Add coverage that ROCM_ATTN accepts the advertised FP8 cache configuration.
  • Update public C-ABI/FP8 capability documentation for the new exposed controls.
  • Rebuild history so the committed spec precedes implementation.
  • Reconcile the issue, spec, and PR body onto one owning row.

The frozen head lacks production-seam and mutation evidence for the behavior it adds.

@ghazni101
ghazni101 force-pushed the row/fp8-kv-decode-attn branch from 934ff06 to db3e689 Compare September 1, 2026 01:46
ghazni101 added a commit to ghazni101/vllm.cpp that referenced this pull request Sep 1, 2026
Four gates for PR mudler#2168 review 5070827757:

G6 (tests/vt/test_rocm_fp8_kv_cache.cpp): exact-geometry reach test for
PagedAttnDecodeGqaF32Q with fp8 KV. Uses hq=16, kv=4, d=128, f32 q/out,
fp8-e4m3 K/V — the exact guard geometry. G4/G4b (hq=2, H=1, D=16) never
reaches the GQA4 dispatch, so deleting it left them green. A file-scope
setenv initializer activates VT_ATTN_DECODE_GQA4=1 before any
PagedAttentionKernelRocm call; G4/G4b's geometry does not match the
guard, so they are not rerouted.

C ABI v24 (tests/capi/test_capi.cpp): kv_cache_dtype defaults to NULL,
and a valid string reaches FromModelDir (fails with MODEL_LOAD, not
INVALID_ARGUMENT). The ABI version pin moves to >= 24.

vllm-cli (tests/vllm/entrypoints/test_cli_kv_cache_dtype.cpp):
--kv-cache-dtype is accepted and reaches the loader (the load fails on
a missing checkpoint, not on an unrecognised argument). Registered
unconditionally; exits 77 without VLLM_CPP_BUILD_EXAMPLES.

ROCM_ATTN (tests/vllm/v1/attention/test_attn_backend_registry.cpp):
supported_kv_cache_dtypes includes fp8 and fp8_e4m3, and
supports_kv_cache_dtype binds the declaration to selection. e5m2 is
NOT advertised.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
@ghazni101

Copy link
Copy Markdown
Contributor Author

All six requirements from review 5070827757 are resolved. The branch was force-pushed (934ff06e2db3e68944); the history was rebuilt so the spec commit (b8a859e1e) precedes the implementation (7bc79e87b), and the branch is rebased onto current main.

1. Exact-geometry ROCm test reaching GQA4 FP8 kernel

test_rocm_fp8_kv_cache.cpp G6 uses hq=16, kv=4, d=128, f32 q/out, fp8-e4m3 KV — the exact PagedAttnDecodeGqaF32Q guard geometry. G4/G4b (hq=2, H=1, D=16) never matched the guard, so deleting the dispatch left them green. A file-scope setenv("VT_ATTN_DECODE_GQA4","1") initializer activates before any PagedAttentionKernelRocm call; G4/G4b's geometry does not match the guard so they are not rerouted.

8/8 cases, 32 assertions, 0 skipped — G6 ran on the RX 7900 XTX.

2. C ABI + vllm-cli end-to-end gate

test_capi.cpp: kv_cache_dtype defaults to NULL; a valid string reaches FromModelDir (fails with MODEL_LOAD, not INVALID_ARGUMENT). ABI version pin moved to >= 24.

New test_cli_kv_cache_dtype.cpp: --kv-cache-dtype is accepted and reaches the loader (the load fails on a missing checkpoint, not on an unrecognised argument). Registered unconditionally; exits 77 without VLLM_CPP_BUILD_EXAMPLES.

68/68 C ABI cases, 676 assertions; 2/2 CLI cases, 12 assertions.

3. ROCM_ATTN FP8 cache config acceptance test

test_attn_backend_registry.cpp: asserts supported_kv_cache_dtypes includes fp8 and fp8_e4m3, supports_kv_cache_dtype binds the declaration to selection, and fp8_e5m2 is NOT advertised.

21/21 cases, 135 assertions.

4. Public C-ABI/FP8 capability documentation

USAGE.md: replaced "Not on the C ABI yet" with the C ABI v24 usage and a code example. FEATURES.md: the fp8 KV cache row no longer says "the C ABI are refused" — it names the ABI v24 field. Added a C-ABI capability table row for KV-cache storage dtype.

5. Spec before implementation

Commit b8a859e1e (spec) precedes 7bc79e87b (implementation). The original commit 4698cccab carried both; the split puts the spec first in history.

6. One owning row

Issue #7, spec, and this PR body all carry Row: GFX1100-TG200. The KV-FP8 engine-matrix row owns the store/read correctness surface; this row owns the decode performance arm on top of it.

Gates

  • check-commit-style.py: OK
  • check-commit-trailers.py: OK
  • test_rocm_fp8_kv_cache: 8/8 (G6 ran on GPU)
  • test_attn_backend_registry: 21/21
  • test_capi: 68/68
  • test_cli_kv_cache_dtype: 2/2

@ghazni101

Copy link
Copy Markdown
Contributor Author

Record anchor fix pushed (db3e6894bb588eabff).

What was wrong

The supported_kv_cache_dtypes insertion in include/vllm/v1/attention/backend.h (commit 0734605) shifted TritonMLABackend::get_kv_cache_shape from :580 to :587. The KERNEL-ATTN-MLA-SPARSE row in .agents/kernel-matrix.md still cited :580, which is now an empty line, making the anchor stale (29 > baseline 28).

Fix

Advanced the citation from backend.h:580 to backend.h:587 where the declaration actually lives. One-line change in .agents/kernel-matrix.md.

CI status at bb588eabff

PR-specific failure resolved:

  • agent-record: success (was failure — stale anchor regression)
  • documentation-checkpoint: success (was failure on main)

Pre-existing failures on main (not caused by this PR):

  • windows-msvc-cpu / windows-msvc-vulkan: test_openai_api_server.exe crash (STATUS_STACK_BUFFER_OVERRUN) — same failure on main at 7a1a987602
  • build-test-cpu: test_gguf_device_fit_reach fails with CHECK( 2 == 1 ) — identical failure on main
  • sanitize-cpu (address,undefined) / (thread): same test_gguf_device_fit_reach failure + pre-existing misaligned address in cpu_matmul_elem.cpp:574

All other gates green: build, plan, verify (cpu), verify (vulkan), build-test-vulkan, build-test-cpu-arm64, device-leakage, commit-protocol-tag, pr-size, cuda-arch-features, vulkan-spirv-freshness, last-gated-commit.

Commit gates:

  • check-commit-style.py --range 7a1a987..HEAD: OK
  • check-commit-trailers.py --range 7a1a987..HEAD: OK

Review requirements (review 5070827757): all six verified present in the code — G6 reach test, C ABI + CLI gates, ROCM_ATTN FP8 acceptance test, public docs, spec-before-implementation history, one owning row.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]

…sue #7)

Scope, upstream chain, design, risks, and gates for widening
PagedAttnDecodeGqaF32Q to accept fp8-e4m3 KV cache pages. The spec
precedes the implementation per AGENTS.md.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
…pport

Add PagedAttnDecodeGqaF32Q — a warp-strided decode attention kernel for
the f32-query x bf16/fp8-KV x f32-output dtype combination that the GGUF
dense path uses. Without this arm, f32-query decode falls through to
PagedAttnOnline, which walks each context token with a per-key
__syncthreads() reduction (~593us/call, 8 calls/token on Qwen3.5-4B).

The kernel fuses QG=4 query heads per KV group, walks the sequence
warp-strided, and does register online softmax with no per-key block
sync. EPL = d/32 (8 at d=256, 4 at d=128). Dispatch is gated behind
VT_ATTN_DECODE_GQA4=1 for the exact geometry (f32 q/out, bf16 or fp8
k/v, d=128 or 256, hq=16, kv=4).

fp8 KV cache support: template PagedAttnDecodeGqaF32Q on TKV (default
__hip_bfloat16) with k_scale/v_scale params. Add LoadRowEplFp8<EPL>
(vectorized uint8_t loads + F8E4M3ToF32Dev dequant x scale) and
LoadRowEplKv<EPL, TKV> (if constexpr dispatch between bf16 and fp8).
Widen the dispatch guard: kBF16 || (kI8 && kv_cache_dtype != kAuto).
The dequant arithmetic is identical to LoadKv(uint8_t*, ...) at line
176 — the fast kernel calls the same dequant the fallback already used.

Benchmark: Qwen3.5-4B Q4_K_M, RX 7900 XTX, ROCm 7.14.0, 128-token
greedy decode, 4 reps:

  ctx=256:    99.94 -> 140.19 tok/s (1.40x), bf16=143.0 (0.98x)
  ctx=1024:   56.28 -> 122.31 tok/s (2.17x), bf16=128.7 (0.95x)
  ctx=4096:   20.53 ->  79.53 tok/s (3.87x), bf16=92.7  (0.86x)
  ctx=8192:   11.08 ->  54.55 tok/s (4.93x), bf16=66.4  (0.82x)
  ctx=16384:   5.78 ->  33.47 tok/s (5.79x), bf16=43.16 (0.78x)

Token-exact: 3/3 simple prompts match the PagedAttnOnline fallback
output byte-for-byte. Divergence at thinking-tag near-ties is the
reduction-order risk the bf16 GQA4 path already carries — same policy
class as VT_ATTN_DECODE_D128. The arm ships opt-in
(VT_ATTN_DECODE_GQA4=1); near-tie adjudication before any default-ON
flip remains owed.

Spec: .agents/specs/rocm-fp8-kv-decode-attn.md
Evidence: docs/bench-evidence/gfx1100-tg200-t3a-20260823.md
Fork issue: #7

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
W6 store/read is on main. This branch's PagedAttnDecodeGqaF32Q arm
reads fp8 KV. Without advertising the dtypes, --kv-cache-dtype fp8 is
refused at the backend registry before the kernel can run.

Fork issue: #7

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-3-FLASH [OMP]
`check-env-doc` reads `std::getenv("VT_ATTN_DECODE_GQA4")` in
`src/vt/rocm/rocm_paged_attn.hip` and the knob was on neither surface:
not documented in `docs/ENVIRONMENT.md` and not on the kernel-internal
allowlist. It is a behavior-changing dispatch gate, not a tuning
switch, so the row documents what setting it routes where, the exact
geometry it guards, and the near-tie caveat the read site's own comment
carries.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-3-FLASH [OMP]
…ffer

The EPL=16 path copied the bf16 LoadRowEplBf16 pattern of loading two
uint4 values (32 bytes), but fp8 elements are 1 byte each so 16 elements
fit in one uint4 (16 bytes). The second load wrote past r[15] into
r[16..31] on a float r[16] array — a stack buffer overflow.

The bug was latent: the dispatch guard only instantiates EPL=4 (d=128)
and EPL=8 (d=256). EPL=16 would need d=512, which the guard excludes.
The static_assert admits EPL=16, so the trap was set for a future d=512
extension. Fixed to a single uint4 load writing r[0..15], matching the
spec design section.

Verified on RX 7900 XTX (gfx1100) in a ROCm 10.0.0 container:
test_rocm_fp8_kv_cache 7/7, test_ops_fp8_kv_cache 8/8 (511 assertions),
test_attn_backend_registry 20/20, test_attn_validate_configuration 21/21,
test_kv_cache_fp8_wiring 31/31 (487 assertions), test_ops_attention 11/11,
test_rocm_backend 9/9 (1065 assertions), test_rocm_arch 9/9.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:glm-5-2 [OMP]
The fp8 KV cache capability landed in W6 but was unreachable from the
CLI because the C ABI (vllm_model_params) did not carry a
kv_cache_dtype field. The server had --kv-cache-dtype; the CLI did
not. Add it as ABI v24: a const char* kv_cache_dtype field appended
to vllm_model_params, mapped to EngineParams.kv_cache_dtype in
vllm_engine_load, and exposed as --kv-cache-dtype in vllm-cli.

NULL or "auto" (the zero-initialized default) is byte-identical to
before. "fp8" or "fp8_e4m3" stores 1-byte fp8-e4m3 K/V.

Served-model gate (Qwen3.5-4B Q4_K_M, RX 7900 XTX, ROCm 10.0.0):
bf16 baseline vs fp8 KV + VT_ATTN_DECODE_GQA4=1, greedy, 256 tokens.
First ~180 tokens byte-identical; divergence only at mid-stream
near-tie moves (the reduction-order difference the spec documents).

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:glm-5-2 [OMP]
Four gates for PR mudler#2168 review 5070827757:

G6 (tests/vt/test_rocm_fp8_kv_cache.cpp): exact-geometry reach test for
PagedAttnDecodeGqaF32Q with fp8 KV. Uses hq=16, kv=4, d=128, f32 q/out,
fp8-e4m3 K/V — the exact guard geometry. G4/G4b (hq=2, H=1, D=16) never
reaches the GQA4 dispatch, so deleting it left them green. A file-scope
setenv initializer activates VT_ATTN_DECODE_GQA4=1 before any
PagedAttentionKernelRocm call; G4/G4b's geometry does not match the
guard, so they are not rerouted.

C ABI v24 (tests/capi/test_capi.cpp): kv_cache_dtype defaults to NULL,
and a valid string reaches FromModelDir (fails with MODEL_LOAD, not
INVALID_ARGUMENT). The ABI version pin moves to >= 24.

vllm-cli (tests/vllm/entrypoints/test_cli_kv_cache_dtype.cpp):
--kv-cache-dtype is accepted and reaches the loader (the load fails on
a missing checkpoint, not on an unrecognised argument). Registered
unconditionally; exits 77 without VLLM_CPP_BUILD_EXAMPLES.

ROCM_ATTN (tests/vllm/v1/attention/test_attn_backend_registry.cpp):
supported_kv_cache_dtypes includes fp8 and fp8_e4m3, and
supports_kv_cache_dtype binds the declaration to selection. e5m2 is
NOT advertised.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
USAGE.md: replace the 'Not on the C ABI yet' section with the C ABI
usage (vllm_model_params.kv_cache_dtype, ABI v24) and a vllm-cli
example. The field defaults to NULL (auto), byte-identical to before.

FEATURES.md: the fp8 KV cache row no longer says 'the C ABI are
refused' — it now names the ABI v24 field. Add a C-ABI capability
table row for KV-cache storage dtype.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
Row: GFX1100-TG200 (campaign, fork issue #5). The KV-FP8 engine-matrix
row owns the store/read correctness surface; this row owns the decode
performance arm on top of it. Issue #7, spec, and PR body now all
reference the same owning row.

## Now updated to record the review-driven gates: G6 reach test, C ABI
v24 gate, vllm-cli gate, ROCM_ATTN acceptance test, public docs, and
the history rebuild that put the spec before implementation.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
…kend.h:587

The supported_kv_cache_dtypes insertion in backend.h (commit 0734605)
shifted TritonMLABackend::get_kv_cache_shape from :580 to :587. The
KERNEL-ATTN-MLA-SPARSE row still cited :580, which is now an empty
line, making the anchor stale (29 > baseline 28). Advance the citation
to :587 where the declaration actually lives.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
@ghazni101
ghazni101 force-pushed the row/fp8-kv-decode-attn branch from bb588ea to e93c0a9 Compare September 1, 2026 16:14
@mudler
mudler merged commit 37e6877 into mudler:main Sep 2, 2026
26 of 29 checks passed
mudler added a commit that referenced this pull request Sep 2, 2026
…he prefill fast path

Row: `GFX1100-TG200`

`PagedAttnPrefillSharedK` is templated on the KV element type, the query type
and the output type, so an fp8 KV cache no longer falls off the fast prefill
path. The fp8 tile load dequantizes each byte with
`F8E4M3ToF32Dev(byte) * scale` into the same bf16 shared-memory tile the bf16
arm fills, leaving the QK dot product, the online softmax and the V
accumulation untouched. This is the prefill half of the arm whose decode half
landed in #2168.

What this tree could check, and what it could not. No CI lane here compiles a
.hip translation unit, so the kernel itself rests on the contributor's own
gfx1100 evidence. Everything the lanes do build passed.

The red lanes on this head are all the tree's, and each was checked rather than
assumed:

`sanitize-cpu (address,undefined)` reports eight failures, and all eight are the
misaligned-borrow class, not this change. Every one of the job's eight
`load of misaligned address` reports comes from `cpu_matmul_elem.cpp:577` (six)
or `cpu_exl3_kernels.cpp:130` (two) -- the exact consumer sites #2581 repairs,
in files this branch does not touch. Note the baseline for that lane grew from
seven tests to eight while this pull request was in flight, because `main`
gained `test_qwen3_dflash2_exl3`, which hits the same defect; that test passes
on #2581's head. Counting the failures would have mis-attributed this. Reading
their signatures does not.

`windows-msvc-cpu` and `windows-msvc-vulkan` are red tree-wide.

The add/add conflict this branch carried on
`.agents/specs/rocm-fp8-kv-decode-attn.md` -- #2168 landed that spec while this
branch still carried the pre-implementation copy of it -- was resolved by the
contributor's own rebase before this merge. Its prefill spec,
`.agents/specs/rocm-fp8-prefill-fastpath.md`, was never contested.

Merged with --no-ff so the contributor's commits keep their authorship.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
Assisted-by: claude-code:claude-opus-5 [Claude Code]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants