Skip to content

feat(BACKEND-ROCM): add keep-quant GEMM providers - #2782

Closed
ghazni101 wants to merge 5 commits into
mudler:mainfrom
ghazni101:row/GFX1100-TG200-F1
Closed

feat(BACKEND-ROCM): add keep-quant GEMM providers#2782
ghazni101 wants to merge 5 commits into
mudler:mainfrom
ghazni101:row/GFX1100-TG200-F1

Conversation

@ghazni101

@ghazni101 ghazni101 commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Closes #2781.
Closes #2927.

Row: BACKEND-ROCM

Merge the reconstructed ROCm keep-quant providers from external pull request
#2782 at 9fcd5d7180bcda2ca7c5aed74d154999a8f59d9e. This no-ff merge preserves
Ghazni's authorship on the three contributor commits.

The providers serve dense and grouped GEMMs for eleven ROCm block formats.
They retain grouped Q8_0 delegation and use the established external registrar.

The reconstruction keys grow-only scratch by queue identity. It refuses cold
or growing allocations during graph capture and preserves warm replay storage.

The GGUF loader admits exactly the formats that the ROCm providers serve.
IQ4_XS remains separate work in #3029. Unsupported formats stay on the
expansion path.

Operator job 7d7fe3a1-9001-4fc3-9463-8e2854f71e33 used the exact source
archive for 9fcd5d718. Its product tree matches the tested 791519aeb tree.
The clean archive has SHA-256
4771a58c553a6b5d0cd0c5332a1b604adbe90f86282d109b900dfa33afa716d7.

The job ran on strix:gpu0, an AMD Radeon 8060S at gfx1151, with ROCm
7.2.4 and HIP 7.2.53211. A fresh HIP configure and build completed.
test_rocm_quant_dot --no-skip passed 5 cases and 145,327 assertions.
test_gguf_keep_quant passed 54 cases and 11,970 assertions.

The earlier 132,094-assertion result came from a stale binary and is not
landing evidence. A broad CTest regex selected unbuilt unrelated targets, so
this record does not use that invocation as evidence.

No gfx1100 speed result is claimed by this merge. The device result establishes
correctness only on the named board.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GPT-5 [Codex]

ghazni101 added a commit to ghazni101/vllm.cpp that referenced this pull request Sep 3, 2026
Adds the VT_GEMV_MMVQ=1 opt-in K-quant decode GEMV arm for MatmulBTQuant,
bit-exact vs the CPU oracle. The arm folds activation quant into the MMVQ
GEMV prologue (deleting the standalone QuantizeQ8KK launch) and widens the
gate to engine dtypes (bf16/f16 activations, bf16/f32 outputs).

Sub-levers:
- lever-B1: VT_GEMV_MMVQ_FOLD_MAX makes the fold crossover tunable at runtime
- lever-B2: VT_SKINNY_BF16=1 f32-out decode-skinny arm for GDN BA projections
- repair: m-gates the whole dispatch and makes the GEMV bit-equal to baseline
- repair-2: host-side dispatch-route counters + F1/F2 routing-witness gates
- lever-B2 test: red-first f32-out decode-skinny gate, true-unset routing window

Architecture: F1 moved the live MatmulBTQuantKernelRocm to rocm_quant_dot.hip
(anonymous namespace, internal linkage). T4a's MMVQ arm lives in
rocm_grouped_gemm.hip's version (external linkage, renamed to *Gdn). This PR
adds delegation: rocm_quant_dot.hip forwards Q4_K/Q5_K/Q6_K calls to the Gdn
version, preserving F1's IQ-type providers while activating T4a's MMVQ arm.

The default path (VT_GEMV_MMVQ unset) is byte-unchanged from F1. The arm is
opt-in and validated by test_rocm_quant_dot (6/6 cases, 719 assertions) and
test_rocm_skinny_f32 (2/2 cases, 51 assertions). Token-identical to upstream
baseline on Qwen3.5-4B Q4_K, 32-token greedy decode, seed 0.

Depends on mudler#2782 (F1 keep-quant GEMM infra).

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
ghazni101 added a commit to ghazni101/vllm.cpp that referenced this pull request Sep 3, 2026
Adds the VT_GEMV_MMVQ=1 opt-in K-quant decode GEMV arm for MatmulBTQuant,
bit-exact vs the CPU oracle. The arm folds activation quant into the MMVQ
GEMV prologue (deleting the standalone QuantizeQ8KK launch) and widens the
gate to engine dtypes (bf16/f16 activations, bf16/f32 outputs).

Sub-levers:
- lever-B1: VT_GEMV_MMVQ_FOLD_MAX makes the fold crossover tunable at runtime
- lever-B2: VT_SKINNY_BF16=1 f32-out decode-skinny arm for GDN BA projections
- repair: m-gates the whole dispatch and makes the GEMV bit-equal to baseline
- repair-2: host-side dispatch-route counters + F1/F2 routing-witness gates
- lever-B2 test: red-first f32-out decode-skinny gate, true-unset routing window

Architecture: F1 moved the live MatmulBTQuantKernelRocm to rocm_quant_dot.hip
(anonymous namespace, internal linkage). T4a's MMVQ arm lives in
rocm_grouped_gemm.hip's version (external linkage, renamed to *Gdn). This PR
adds delegation: rocm_quant_dot.hip forwards Q4_K/Q5_K/Q6_K calls to the Gdn
version, preserving F1's IQ-type providers while activating T4a's MMVQ arm.

The default path (VT_GEMV_MMVQ unset) is byte-unchanged from F1. The arm is
opt-in and validated by test_rocm_quant_dot (6/6 cases, 719 assertions) and
test_rocm_skinny_f32 (2/2 cases, 51 assertions). Token-identical to upstream
baseline on Qwen3.5-4B Q4_K, 32-token greedy decode, seed 0.

Depends on mudler#2782 (F1 keep-quant GEMM infra).

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
@ghazni101
ghazni101 force-pushed the row/GFX1100-TG200-F1 branch from dc036a4 to 29eebfc Compare September 3, 2026 19:24
ghazni101 added a commit to ghazni101/vllm.cpp that referenced this pull request Sep 3, 2026
Adds the VT_GEMV_MMVQ=1 opt-in K-quant decode GEMV arm for MatmulBTQuant,
bit-exact vs the CPU oracle. The arm folds activation quant into the MMVQ
GEMV prologue (deleting the standalone QuantizeQ8KK launch) and widens the
gate to engine dtypes (bf16/f16 activations, bf16/f32 outputs).

Sub-levers:
- lever-B1: VT_GEMV_MMVQ_FOLD_MAX makes the fold crossover tunable at runtime
- lever-B2: VT_SKINNY_BF16=1 f32-out decode-skinny arm for GDN BA projections
- repair: m-gates the whole dispatch and makes the GEMV bit-equal to baseline
- repair-2: host-side dispatch-route counters + F1/F2 routing-witness gates
- lever-B2 test: red-first f32-out decode-skinny gate, true-unset routing window

Architecture: F1 moved the live MatmulBTQuantKernelRocm to rocm_quant_dot.hip
(anonymous namespace, internal linkage). T4a's MMVQ arm lives in
rocm_grouped_gemm.hip's version (external linkage, renamed to *Gdn). This PR
adds delegation: rocm_quant_dot.hip forwards Q4_K/Q5_K/Q6_K calls to the Gdn
version, preserving F1's IQ-type providers while activating T4a's MMVQ arm.

The default path (VT_GEMV_MMVQ unset) is byte-unchanged from F1. The arm is
opt-in and validated by test_rocm_quant_dot (6/6 cases, 719 assertions) and
test_rocm_skinny_f32 (2/2 cases, 51 assertions). Token-identical to upstream
baseline on Qwen3.5-4B Q4_K, 32-token greedy decode, seed 0.

Depends on mudler#2782 (F1 keep-quant GEMM infra).

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
ghazni101 added a commit to ghazni101/vllm.cpp that referenced this pull request Sep 3, 2026
…Norm epilogue

Lever-C adds an opt-in fused norm-quant epilogue (VT_NORM_QUANT_FUSED=1):
RmsNormRowKernel emits the row's Q8_K blocks alongside its normal output,
and MatmulBTQuant's K-quant branch skips the standalone QuantizeQ8KK when
the consuming activation matches the producer token. Byte-identical to the
standalone path by construction (shared QuantQ8KSBlock body).

New files:
- src/vt/rocm/rocm_act_quant.h: shared Q8_K quant-block body
- src/vt/rocm/rocm_norm_quant_bridge.h: producer-consumer token contract

Also fixes T4a routing counter placement (moved outside anonymous namespace
for external linkage) and restores VT_GEMV_MMVQ_FOLD_MAX env var reading
that was lost during cherry-pick conflict resolution.

The default path (VT_NORM_QUANT_FUSED unset) is byte-unchanged. Validated by
test_rocm_quant_dot (12/12 cases, 797 assertions). Token-identical to upstream
baseline on Qwen3.5-4B Q4_K, 32-token greedy decode, seed 0.

Depends on mudler#2782 (F1) and mudler#2790 (T4a).

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
@ghazni101
ghazni101 force-pushed the row/GFX1100-TG200-F1 branch from 29eebfc to 73478f6 Compare September 4, 2026 07:34
ghazni101 added a commit to ghazni101/vllm.cpp that referenced this pull request Sep 4, 2026
Adds the VT_GEMV_MMVQ=1 opt-in K-quant decode GEMV arm for MatmulBTQuant,
bit-exact vs the CPU oracle. The arm folds activation quant into the MMVQ
GEMV prologue (deleting the standalone QuantizeQ8KK launch) and widens the
gate to engine dtypes (bf16/f16 activations, bf16/f32 outputs).

Sub-levers:
- lever-B1: VT_GEMV_MMVQ_FOLD_MAX makes the fold crossover tunable at runtime
- lever-B2: VT_SKINNY_BF16=1 f32-out decode-skinny arm for GDN BA projections
- repair: m-gates the whole dispatch and makes the GEMV bit-equal to baseline
- repair-2: host-side dispatch-route counters + F1/F2 routing-witness gates
- lever-B2 test: red-first f32-out decode-skinny gate, true-unset routing window

Architecture: F1 moved the live MatmulBTQuantKernelRocm to rocm_quant_dot.hip
(anonymous namespace, internal linkage). T4a's MMVQ arm lives in
rocm_grouped_gemm.hip's version (external linkage, renamed to *Gdn). This PR
adds delegation: rocm_quant_dot.hip forwards Q4_K/Q5_K/Q6_K calls to the Gdn
version, preserving F1's IQ-type providers while activating T4a's MMVQ arm.

The default path (VT_GEMV_MMVQ unset) is byte-unchanged from F1. The arm is
opt-in and validated by test_rocm_quant_dot (6/6 cases, 719 assertions) and
test_rocm_skinny_f32 (2/2 cases, 51 assertions). Token-identical to upstream
baseline on Qwen3.5-4B Q4_K, 32-token greedy decode, seed 0.

Depends on mudler#2782 (F1 keep-quant GEMM infra).

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
ghazni101 added a commit to ghazni101/vllm.cpp that referenced this pull request Sep 4, 2026
…Norm epilogue

Lever-C adds an opt-in fused norm-quant epilogue (VT_NORM_QUANT_FUSED=1):
RmsNormRowKernel emits the row's Q8_K blocks alongside its normal output,
and MatmulBTQuant's K-quant branch skips the standalone QuantizeQ8KK when
the consuming activation matches the producer token. Byte-identical to the
standalone path by construction (shared QuantQ8KSBlock body).

New files:
- src/vt/rocm/rocm_act_quant.h: shared Q8_K quant-block body
- src/vt/rocm/rocm_norm_quant_bridge.h: producer-consumer token contract

Also fixes T4a routing counter placement (moved outside anonymous namespace
for external linkage) and restores VT_GEMV_MMVQ_FOLD_MAX env var reading
that was lost during cherry-pick conflict resolution.

The default path (VT_NORM_QUANT_FUSED unset) is byte-unchanged. Validated by
test_rocm_quant_dot (12/12 cases, 797 assertions). Token-identical to upstream
baseline on Qwen3.5-4B Q4_K, 32-token greedy decode, seed 0.

Depends on mudler#2782 (F1) and mudler#2790 (T4a).

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
ghazni101 added a commit to ghazni101/vllm.cpp that referenced this pull request Sep 6, 2026
Adds the VT_GEMV_MMVQ=1 opt-in K-quant decode GEMV arm for MatmulBTQuant,
bit-exact vs the CPU oracle. The arm folds activation quant into the MMVQ
GEMV prologue (deleting the standalone QuantizeQ8KK launch) and widens the
gate to engine dtypes (bf16/f16 activations, bf16/f32 outputs).

Sub-levers:
- lever-B1: VT_GEMV_MMVQ_FOLD_MAX makes the fold crossover tunable at runtime
- lever-B2: VT_SKINNY_BF16=1 f32-out decode-skinny arm for GDN BA projections
- repair: m-gates the whole dispatch and makes the GEMV bit-equal to baseline
- repair-2: host-side dispatch-route counters + F1/F2 routing-witness gates
- lever-B2 test: red-first f32-out decode-skinny gate, true-unset routing window

Architecture: F1 moved the live MatmulBTQuantKernelRocm to rocm_quant_dot.hip
(anonymous namespace, internal linkage). T4a's MMVQ arm lives in
rocm_grouped_gemm.hip's version (external linkage, renamed to *Gdn). This PR
adds delegation: rocm_quant_dot.hip forwards Q4_K/Q5_K/Q6_K calls to the Gdn
version, preserving F1's IQ-type providers while activating T4a's MMVQ arm.

The default path (VT_GEMV_MMVQ unset) is byte-unchanged from F1. The arm is
opt-in and validated by test_rocm_quant_dot (6/6 cases, 719 assertions) and
test_rocm_skinny_f32 (2/2 cases, 51 assertions). Token-identical to upstream
baseline on Qwen3.5-4B Q4_K, 32-token greedy decode, seed 0.

Rebased onto the external-contributor landing branch (staging tip
b9f2ef4), which already carries F1 (mudler#2782) and its grouped-Q8_0 repair
(mudler#2927). This version carries NONE of the removals the previous base commit
51f5222 made: the ten-row kCases table, kMaxNmseErr/nmse_ref_max and the
three F1 provider cases are restored beside this arm's kKQuantCases (mudler#2938);
Dp4a keeps the __ockl_sdot4 hardware dot (mudler#2939); the documented
VT_ROCM_Q8K_BLOCK selector (SelectQ8KQuantArm/LaunchQ8KQuantizer), the mudler#2472
cooperative gfx1100 default (QuantizeQ8KCooperativeK) and the
VT_ROCM_Q6K_SMALL_PRIVATE A/B arm are restored with their witness helpers;
the shared bench-evidence file keeps lever B1's section 14 record, whose
truncation this branch had carried.

Depends on mudler#2782 (F1 keep-quant GEMM infra).

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
Assisted-by: AGENT:OMEN-ALPHA [OMP]
ghazni101 added a commit to ghazni101/vllm.cpp that referenced this pull request Sep 6, 2026
…Norm epilogue

Lever-C adds an opt-in fused norm-quant epilogue (VT_NORM_QUANT_FUSED=1):
RmsNormRowKernel emits the row's Q8_K blocks alongside its normal output,
and MatmulBTQuant's K-quant branch skips the standalone QuantizeQ8KK when
the consuming activation matches the producer token. Byte-identical to the
standalone path by construction (shared QuantQ8KSBlock body).

New files:
- src/vt/rocm/rocm_act_quant.h: shared Q8_K quant-block body
- src/vt/rocm/rocm_norm_quant_bridge.h: producer-consumer token contract

Also fixes T4a routing counter placement (moved outside anonymous namespace
for external linkage) and restores VT_GEMV_MMVQ_FOLD_MAX env var reading
that was lost during cherry-pick conflict resolution.

The default path (VT_NORM_QUANT_FUSED unset) is byte-unchanged. Validated by
test_rocm_quant_dot (12/12 cases, 797 assertions). Token-identical to upstream
baseline on Qwen3.5-4B Q4_K, 32-token greedy decode, seed 0.

Depends on mudler#2782 (F1) and mudler#2790 (T4a).

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
ghazni101 added a commit to ghazni101/vllm.cpp that referenced this pull request Sep 6, 2026
The grouped arm delegates Q4_K/Q5_K/Q6_K to MatmulBTQuantGroupedKernelRocmGdn
but not Q8_0, and Q8_0 has no arm in rocm_quant_dot.hip either, so a grouped
Q8_0 expert GEMM throws on a path main serves. Add Q8_0 to the delegation list
and a test case that fails when it is dropped.

Addressing localai-org-maint-bot review on mudler#2782 (issue mudler#2927).

FOLLOWING_AGENTS_PROTOCOL

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

Copy link
Copy Markdown
Contributor Author

Rebased onto upstream/main (6f5e9dc) and applied the #2927 repair: added DType::kQ8_0 to the grouped delegation list in MatmulBTQuantGroupedKernelRocm so grouped Q8_0 expert GEMMs route to MatmulBTQuantGroupedKernelRocmGdn instead of throwing. Added a q8_0 case to the kCases test table so the grouped arm has coverage that fails when the delegation is dropped.

The base is now origin/main, not stage/ext-prs-2026-09-04. Ping for re-review.

FOLLOWING_AGENTS_PROTOCOL

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

@VikashLoomba

Copy link
Copy Markdown
Contributor

The current 876736c329bd573457576a63833b9a97a0749681 has a P1 linkage defect in the #2781 foundation flow. This is an immutable-source finding, not a claimed HIP build result.

rocm_grouped_gemm.hip:1323,1456 renames the only external definitions to MatmulBTQuantKernelRocmGdn and MatmulBTQuantGroupedKernelRocmGdn. The old-name replacements at rocm_quant_dot.hip:928,992 sit inside the anonymous namespace opened at line 53 and closed at line 1074. They cannot satisfy the external references retained by rocm_ops.hip:259–263.

The landed #3001 fused provider also calls the old external grouped symbol twice at rocm_moe_gate_up_swiglu.hip:160–161. Removing only the registrar leaves that consumer unresolved. Please restore compatible external entry points and reconcile registration ownership, then run a fresh HIP build/link and the provider tests. A complete comparison of all 6,033 source-tree blobs against the immutable base found no other replacement external definition. I independently verified the four affected files against their Git blob IDs.

The grouped Q8_0 delegation omission is repaired in this head and should no longer be reported as missing. The current test source implies three cases and 145,303 assertions if every device loop runs; that is a derived expected count, not an execution result.

The maintainer’s GLM hardware result also corrects the old blanket reachability objection. That opt-in production path reached the grouped provider and refused a dtype. The actual refused dtype remains unidentified, and the printed list includes Q4_0 and MXFP4, which this patch does not add. Please qualify the claimed fix with the exact dtype and consumer. #3019 and #2942 retain the separate admission work.

The gfx1100 WMMA requirement remains separate. This patch adds no RDNA3 WMMA tile; the inherited matrix path admits gfx1200/gfx1201. #2109 closed through #2991 on 6 September, and that landed spec explicitly leaves RDNA3 to separate work. No device or performance acceptance is claimed by this audit.

ghazni101 and others added 5 commits September 8, 2026 05:05
… kROCM

The GGUF loader routes a block-typed weight to MatmulBTQuant whenever the
running device has the provider, so registering these two ops lights up
keep-quant compute on every ROCm board with no model-path change: the
dense and grouped MoE towers stage once through ResidentWeight and
dispatch to the new device GEMM.

Coverage mirrors the CUDA sibling exactly — the ten Q8_K-family
encodings plus a native Q8_0 arm. The integer dots are the portable
scalar forms of the CPU reference bodies in the CPU accumulation order,
because gfx1100 exposes no signed byte dot (v_dot4_i32_iu8 is
unsigned-only; sdot4 needs a feature this target does not offer), and
the gate is bit-exactness against the CPU tier at NMSE 1e-6 with the f64
dequant band at 5e-4. Unsupported dtypes throw naming the dtype instead
of silently falling back to a host kernel that cannot follow device
pointers; VT_GGUF_KEEP_QUANT=0 restores load-time expansion.

Gates on gfx1100 / ROCm 7.14.0: test_rocm_quant_dot 132,094 assertions
green across all ten encodings (decode through prefill shapes, broadcast
and per-row grouped arms over a poisoned output buffer), focused
ctest 'rocm|cross_device|quant' 20/21 with only the pre-existing
MoeSiluMul bf16 exactness failure (mudler#1588) remaining, and an end-to-end
Qwen3.5-0.8B Q4_K_M decode that is deterministic on device.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:ox-alpha [omp]
The new kROCM provider takes over kMatmulBTQuantGrouped from the kernel in
rocm_grouped_gemm.hip and delegates Q4_K/Q5_K/Q6_K back to it, but not Q8_0.
Q8_0 has no arm in rocm_quant_dot.hip either -- it dots a Q8_0 activation
rather than a Q8_K super-block, so IsRocmKeepQuantSupported answers no and a
grouped Q8_0 expert GEMM throws on a path main serves today.

Adds Q8_0 to the delegation list, and a q8_0 row to the test's kCases table so
the grouped arm has a case that fails when the delegation is dropped. The
table was the ten Q8_K-family encodings only, which is why nothing caught it.

Closes mudler#2927.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5-1m [claude-code]
…CM provider"

This reverts commit 82d99ea. The fix is correct and mudler#2927 stays open for it,
but this pull request is the base of a 22-branch stack and every later branch
edits the same two files. Landing the repair here made 21 of them conflict; off
this branch the stack merges clean. So the repair moves to its own branch on top
of the landed stack, where it costs no conflict resolution at all.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5-1m [claude-code]
The grouped arm delegates Q4_K/Q5_K/Q6_K to MatmulBTQuantGroupedKernelRocmGdn
but not Q8_0, and Q8_0 has no arm in rocm_quant_dot.hip either, so a grouped
Q8_0 expert GEMM throws on a path main serves. Add Q8_0 to the delegation list
and a test case that fails when it is dropped.

Addressing localai-org-maint-bot review on mudler#2782 (issue mudler#2927).

FOLLOWING_AGENTS_PROTOCOL

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

MatmulBTQuantKernelRocm and MatmulBTQuantGroupedKernelRocm were defined
inside an anonymous namespace while rocm_ops.hip declares and registers
them for kROCM and rocm_moe_gate_up_swiglu.hip calls the grouped entry
point, so every executable failed to link with undefined symbols. Close
the anonymous namespace before the two providers so they keep external
linkage, and delete this file's own Registrar: rocm_ops.hip's registrar
already registers both ops, and a second registration of the same
OpId+DeviceType would make provider selection depend on static-init
order across translation units.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5.3-Flash [ZCode]
ghazni101 added a commit to ghazni101/vllm.cpp that referenced this pull request Sep 8, 2026
Adds the VT_GEMV_MMVQ=1 opt-in K-quant decode GEMV arm for MatmulBTQuant,
bit-exact vs the CPU oracle. The arm folds activation quant into the MMVQ
GEMV prologue (deleting the standalone QuantizeQ8KK launch) and widens the
gate to engine dtypes (bf16/f16 activations, bf16/f32 outputs).

Sub-levers:
- lever-B1: VT_GEMV_MMVQ_FOLD_MAX makes the fold crossover tunable at runtime
- lever-B2: VT_SKINNY_BF16=1 f32-out decode-skinny arm for GDN BA projections
- repair: m-gates the whole dispatch and makes the GEMV bit-equal to baseline
- repair-2: host-side dispatch-route counters + F1/F2 routing-witness gates
- lever-B2 test: red-first f32-out decode-skinny gate, true-unset routing window

Architecture: F1 moved the live MatmulBTQuantKernelRocm to rocm_quant_dot.hip
(anonymous namespace, internal linkage). T4a's MMVQ arm lives in
rocm_grouped_gemm.hip's version (external linkage, renamed to *Gdn). This PR
adds delegation: rocm_quant_dot.hip forwards Q4_K/Q5_K/Q6_K calls to the Gdn
version, preserving F1's IQ-type providers while activating T4a's MMVQ arm.

The default path (VT_GEMV_MMVQ unset) is byte-unchanged from F1. The arm is
opt-in and validated by test_rocm_quant_dot (6/6 cases, 719 assertions) and
test_rocm_skinny_f32 (2/2 cases, 51 assertions). Token-identical to upstream
baseline on Qwen3.5-4B Q4_K, 32-token greedy decode, seed 0.

Rebased onto the external-contributor landing branch (staging tip
b9f2ef4), which already carries F1 (mudler#2782) and its grouped-Q8_0 repair
(mudler#2927). This version carries NONE of the removals the previous base commit
51f5222 made: the ten-row kCases table, kMaxNmseErr/nmse_ref_max and the
three F1 provider cases are restored beside this arm's kKQuantCases (mudler#2938);
Dp4a keeps the __ockl_sdot4 hardware dot (mudler#2939); the documented
VT_ROCM_Q8K_BLOCK selector (SelectQ8KQuantArm/LaunchQ8KQuantizer), the mudler#2472
cooperative gfx1100 default (QuantizeQ8KCooperativeK) and the
VT_ROCM_Q6K_SMALL_PRIVATE A/B arm are restored with their witness helpers;
the shared bench-evidence file keeps lever B1's section 14 record, whose
truncation this branch had carried.

Depends on mudler#2782 (F1 keep-quant GEMM infra).

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
Assisted-by: AGENT:OMEN-ALPHA [OMP]
ghazni101 added a commit to ghazni101/vllm.cpp that referenced this pull request Sep 8, 2026
…Norm epilogue

Lever-C adds an opt-in fused norm-quant epilogue (VT_NORM_QUANT_FUSED=1):
RmsNormRowKernel emits the row's Q8_K blocks alongside its normal output,
and MatmulBTQuant's K-quant branch skips the standalone QuantizeQ8KK when
the consuming activation matches the producer token. Byte-identical to the
standalone path by construction (shared QuantQ8KSBlock body).

New files:
- src/vt/rocm/rocm_act_quant.h: shared Q8_K quant-block body
- src/vt/rocm/rocm_norm_quant_bridge.h: producer-consumer token contract

Also fixes T4a routing counter placement (moved outside anonymous namespace
for external linkage) and restores VT_GEMV_MMVQ_FOLD_MAX env var reading
that was lost during cherry-pick conflict resolution.

The default path (VT_NORM_QUANT_FUSED unset) is byte-unchanged. Validated by
test_rocm_quant_dot (12/12 cases, 797 assertions). Token-identical to upstream
baseline on Qwen3.5-4B Q4_K, 32-token greedy decode, seed 0.

Depends on mudler#2782 (F1) and mudler#2790 (T4a).

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
@ghazni101
ghazni101 force-pushed the row/GFX1100-TG200-F1 branch from 876736c to 35063b2 Compare September 8, 2026 05:32
ghazni101 added a commit to ghazni101/vllm.cpp that referenced this pull request Sep 8, 2026
Adds the VT_GEMV_MMVQ=1 opt-in K-quant decode GEMV arm for MatmulBTQuant,
bit-exact vs the CPU oracle. The arm folds activation quant into the MMVQ
GEMV prologue (deleting the standalone QuantizeQ8KK launch) and widens the
gate to engine dtypes (bf16/f16 activations, bf16/f32 outputs).

Sub-levers:
- lever-B1: VT_GEMV_MMVQ_FOLD_MAX makes the fold crossover tunable at runtime
- lever-B2: VT_SKINNY_BF16=1 f32-out decode-skinny arm for GDN BA projections
- repair: m-gates the whole dispatch and makes the GEMV bit-equal to baseline
- repair-2: host-side dispatch-route counters + F1/F2 routing-witness gates
- lever-B2 test: red-first f32-out decode-skinny gate, true-unset routing window

Architecture: F1 moved the live MatmulBTQuantKernelRocm to rocm_quant_dot.hip
(anonymous namespace, internal linkage). T4a's MMVQ arm lives in
rocm_grouped_gemm.hip's version (external linkage, renamed to *Gdn). This PR
adds delegation: rocm_quant_dot.hip forwards Q4_K/Q5_K/Q6_K calls to the Gdn
version, preserving F1's IQ-type providers while activating T4a's MMVQ arm.

The default path (VT_GEMV_MMVQ unset) is byte-unchanged from F1. The arm is
opt-in and validated by test_rocm_quant_dot (6/6 cases, 719 assertions) and
test_rocm_skinny_f32 (2/2 cases, 51 assertions). Token-identical to upstream
baseline on Qwen3.5-4B Q4_K, 32-token greedy decode, seed 0.

Rebased onto the external-contributor landing branch (staging tip
b9f2ef4), which already carries F1 (mudler#2782) and its grouped-Q8_0 repair
(mudler#2927). This version carries NONE of the removals the previous base commit
51f5222 made: the ten-row kCases table, kMaxNmseErr/nmse_ref_max and the
three F1 provider cases are restored beside this arm's kKQuantCases (mudler#2938);
Dp4a keeps the __ockl_sdot4 hardware dot (mudler#2939); the documented
VT_ROCM_Q8K_BLOCK selector (SelectQ8KQuantArm/LaunchQ8KQuantizer), the mudler#2472
cooperative gfx1100 default (QuantizeQ8KCooperativeK) and the
VT_ROCM_Q6K_SMALL_PRIVATE A/B arm are restored with their witness helpers;
the shared bench-evidence file keeps lever B1's section 14 record, whose
truncation this branch had carried.

Depends on mudler#2782 (F1 keep-quant GEMM infra).

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
Assisted-by: AGENT:OMEN-ALPHA [OMP]
ghazni101 added a commit to ghazni101/vllm.cpp that referenced this pull request Sep 8, 2026
…Norm epilogue

Lever-C adds an opt-in fused norm-quant epilogue (VT_NORM_QUANT_FUSED=1):
RmsNormRowKernel emits the row's Q8_K blocks alongside its normal output,
and MatmulBTQuant's K-quant branch skips the standalone QuantizeQ8KK when
the consuming activation matches the producer token. Byte-identical to the
standalone path by construction (shared QuantQ8KSBlock body).

New files:
- src/vt/rocm/rocm_act_quant.h: shared Q8_K quant-block body
- src/vt/rocm/rocm_norm_quant_bridge.h: producer-consumer token contract

Also fixes T4a routing counter placement (moved outside anonymous namespace
for external linkage) and restores VT_GEMV_MMVQ_FOLD_MAX env var reading
that was lost during cherry-pick conflict resolution.

The default path (VT_NORM_QUANT_FUSED unset) is byte-unchanged. Validated by
test_rocm_quant_dot (12/12 cases, 797 assertions). Token-identical to upstream
baseline on Qwen3.5-4B Q4_K, 32-token greedy decode, seed 0.

Depends on mudler#2782 (F1) and mudler#2790 (T4a).

FOLLOWING_AGENTS_PROTOCOL

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

@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 current head 35063b2. The earlier external-linkage and grouped-Q8_0 delegation findings are repaired.

The scratch allocation still needs capture-lifetime coverage before this can land. In src/vt/rocm/rocm_quant_dot.hip:732-741, EnsureScratch publishes hipMallocAsync storage on first use or growth without checking capture state. The cache at lines 712-727 keys ownership by hipStream_t. This retains the allocation/lifetime pattern that #3062 repaired in the sampling path. Please gate cold capture, warm replay, growth during capture, eager reuse before replay, and queue lifetime on the actual provider. This is a static source concern, not a claimed reproduced device failure on this head.

The PR body also says the old registration is removed, but current rocm_ops.hip:259-263 retains the registration and the replacements are now exported. Reconcile the description with the repaired head. A fresh HIP link and current-head provider/runtime results remain required; historical counts are not those results. #2781 retains ownership of this provider work.

@localai-org-maint-bot localai-org-maint-bot changed the title feat(KERNEL-QUANT-CIQ-GEMM-ROCM): land the W1 keep-quant providers on kROCM feat(BACKEND-ROCM): add keep-quant GEMM providers Sep 9, 2026
mudler pushed a commit that referenced this pull request Sep 9, 2026
The grouped arm delegates Q4_K/Q5_K/Q6_K to MatmulBTQuantGroupedKernelRocmGdn
but not Q8_0, and Q8_0 has no arm in rocm_quant_dot.hip either, so a grouped
Q8_0 expert GEMM throws on a path main serves. Add Q8_0 to the delegation list
and a test case that fails when it is dropped.

Addressing localai-org-maint-bot review on #2782 (issue #2927).

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GLM-5-2 [OMP]
mudler added a commit that referenced this pull request Sep 9, 2026
Closes #2781.
Closes #2927.

Row: `BACKEND-ROCM`

Merge the reconstructed ROCm keep-quant providers from external pull request
#2782 at `9fcd5d7180bcda2ca7c5aed74d154999a8f59d9e`. This no-ff merge preserves
Ghazni's authorship on the three contributor commits.

The providers serve dense and grouped GEMMs for eleven ROCm block formats.
They retain grouped Q8_0 delegation and use the established external registrar.

The reconstruction keys grow-only scratch by queue identity. It refuses cold
or growing allocations during graph capture and preserves warm replay storage.

The GGUF loader admits exactly the formats that the ROCm providers serve.
IQ4_XS remains separate work in #3029. Unsupported formats stay on the
expansion path.

Operator job `7d7fe3a1-9001-4fc3-9463-8e2854f71e33` used the exact source
archive for `9fcd5d718`. Its product tree matches the tested `791519aeb` tree.
The clean archive has SHA-256
`4771a58c553a6b5d0cd0c5332a1b604adbe90f86282d109b900dfa33afa716d7`.

The job ran on `strix:gpu0`, an AMD Radeon 8060S at `gfx1151`, with ROCm
7.2.4 and HIP 7.2.53211. A fresh HIP configure and build completed.
`test_rocm_quant_dot --no-skip` passed 5 cases and 145,327 assertions.
`test_gguf_keep_quant` passed 54 cases and 11,970 assertions.

The earlier 132,094-assertion result came from a stale binary and is not
landing evidence. A broad CTest regex selected unbuilt unrelated targets, so
this record does not use that invocation as evidence.

No gfx1100 speed result is claimed by this merge. The device result establishes
correctness only on the named board.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:GPT-5 [Codex]
@localai-org-maint-bot

Copy link
Copy Markdown
Collaborator

Landed through the reviewed reconstruction at e09bf32. The no-ff merge preserves the three contributor commits and their authorship. The reconstruction adds queue-owned capture-safe scratch, restores grouped Q8_0 delegation, admits the supported formats through the production GGUF loader, and reconciles the affected records. The exact merge tree passed the operator HIP gate on strix:gpu0: 5/5 provider cases with 145,327 assertions and 54/54 loader cases with 11,970 assertions. Closing this original head as superseded by the landed reconstruction.

localai-org-maint-bot pushed a commit that referenced this pull request Sep 11, 2026
## Row

`BACKEND-ROCM-F16-WEIGHTS`. Refs #3092. Refs #3106.

## What changed

ROCm retains supported dense and embedding GGUF weights in F16 storage.
Each retained operand carries its resolved value dtype, so BF16 model
arithmetic rounds the file values before multiplication or gathering.
Ordinary NN/BT multiplication and both embedding ID widths reach native
ROCm providers. Queue and graph ownership release transient conversion
scratch without retaining a permanent converted weight copy.

The default Qwen3.5 dense registry supplies the value dtype and rejects
incompatible explicit model dtypes. Other loaders and stacked experts
preserve expansion. This change integrates the reviewed full-attention
consumer prerequisite from #3101 and its runner regression correction
under #3098. It is independent of #2782 and changes no CI configuration.

## Before starting

- The gap was verified at `6db4bef906859e864c82523c01107473f7dcca29`
against the code, tests, issues, pull requests, and owning records.
- One pull request carries specification
`4486d24f07ce197155fa2b37c1ff590cdbe290e7` before implementation. The
scratch-lifetime amendment also precedes its product changes.
- The canonical child inventory and evidence are in
`.agents/specs/rocm-f16-weights.md`. The child remains `ACTIVE`; the
parent lifecycle does not change.
- The design follows pinned vLLM `e126687a9a` and GGUF plugin
`d4c1f0d082` through parameter creation, destination-dtype conversion,
and native dispatch.

## Evidence

CPU ownership and metadata tests, physical gfx1100 primitive and
lifetime tests, graph dedup, and two-device controls pass. The new
registry control passes 4 cases and 107 assertions. The complete CPU
operand-contract suite passes 6 cases and 240 assertions. Guard-deletion
mutations fail the new registry, embedding-provider, and NN-compute
assertions; the unchanged controls pass. Scoped restoration covers
absent, empty, and nonempty environment values and both provider states.

The unchanged full-attention runner fixture now passes 18 assertions
through successful execution, attention-cache writes, sampling, and
request feedback. All 41 CPU runner cases pass with 1,914 assertions.
Restoring unconditional dense GDN validation fails at the original
refusal. The committed #3098 amendment precedes this test-only repair.

`ctest --test-dir build-repair-cpu --output-on-failure -j 1` passes 703
cases, skips 12, and retains the single #3102 baseline failure out of
716. The operator runs the complete HIP suite under the GPU mutex with
both devices visible, provider statistics enabled, and graph dedup
disabled: 692 pass, 12 skip, and 20 fail out of 724. Every one of the 19
baseline failures matches the pristine diagnostic and assertion summary
exactly. The remaining failure is #3106. The added public full-attention
completion target passes.

`bash scripts/agent-preflight.sh --staged` exits zero with every
executed check passing and 678 translation units compiled. Its five
argument-dependent skips are qualified by an explicit passing CPU ISA
audit, passing PR #3095 classification, and inapplicable ARM/CUDA/Triton
artifacts. Exact-range style, trailer, classification, Now, and diff
checks pass on `9cf2bc9505fc377dd5ef707b15c1122e6f09c60d`.

The spec records exact commands, source and binary hashes, skips, and
baseline comparisons. Root verifies all 4,157 source files and 1,006
declared HIP inputs before and after the full run. The operator's full
preflight on `9cf2bc9505fc377dd5ef707b15c1122e6f09c60d` also passed,
including all 678 affected translation units. Fresh scoped review passed
the three F16 guards, the prerequisite integration, and the runner
regression. A separate implementer corrected the paged-attention source
citation. Fresh record review passed on
`4137b96369467e925bfdf0738e5bad013c89b58f`. All 7,274 other tracked
files retain their tested bytes and modes. The operator verified the
one-line delta and reran the applicable record, anchor,
compilation-scope, and exact-range gates before publishing that commit.

## Repair round (heads `15d8e1682` and `6607faea2`)

The committed spec and fix complete native unfused attention. Fresh
review of `15d8e1682` returned PASS with no findings: four CPU guard
mutations redden both model modes (default and explicitly unfused), and
the operator's six GPU mutation gates each redden its guarantee on
gfx1100: G1 unregisters the split and reproduces the recorded pre-fix
refusal at the production regression (57 of 58, 10,457 assertions, `vt:
no kernel for op AttnGateSplit`), G2 swaps the per-head query/gate
layout, G3 replaces the nearest-even BF16 narrowing, G4 makes the gate
widening lossy, G5 modifies the input, and G6 removes the current-device
binding. Pristine rebuilt-head reruns of the five receipt gates exit
zero. The operator receipts, the review report, and the mutation logs
are retained with the row evidence, and the full preflight at
`6607faea2` exits zero with the argument-dependent skips separately
recorded.

## Speed claims

This pull request makes no speed, latency, memory-ratio, or
invocation-parity claim. The capacity-four materialized-oracle subcase
matches all 256 generated IDs across both repeats. Matching rocprofv3
artifacts capture both executing paths, but native BF16-to-F32 outputs
and atomics policy differ from the primary BF16-to-BF16 path.

## Honest gaps

- F16-G3 is resolved at this head: the branch carries the committed
`BACKEND-ROCM-ATTN-GATE-SPLIT` spec, the native ROCm `AttnGateSplit`
kernel and its registration, and the model guards that reach it. The
complete HIP GGUF test passes all 58 cases with 10,970 assertions, and
#3106 closes when this change lands.
- Native D1 repeatability and the primary arithmetic comparison remain
failing under #2773. The identical GGUF primary remains pending under
#3092 and the plugin's recorded limitations; #2624 owns the separate
Qwen3.8 gateability measurement. The prerequisite's actual pinned engine
attempt refuses `Qwen3_5TextConfig` before producing a token.
- CPU token-anchor failure #3102 and HIP baseline failures #3070/#3105
retain their recorded diagnostics. Ownership does not waive any
correctness gate.
- F16 model activations and outputs, RMSNorm activation support,
stacked-expert retention, and other model-loader admission are outside
this row. Public checkpoint pins and refused arms are recorded in
`docs/USAGE.md`.
- The row remains `ACTIVE`. This session publishes for user review and
does not merge.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Codex:gpt-6-astra [Codex CLI]

---------

Co-authored-by: Ettore Di Giacinto <mudler@localai.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

4 participants