Skip to content

HIP : route Q6_K through MMQ up to ne11 = 1024 on RDNA 3.5 - #38

Open
Nyovelt wants to merge 1 commit into
halo-box:masterfrom
Nyovelt:strix/q6k-mmq-rdna35
Open

HIP : route Q6_K through MMQ up to ne11 = 1024 on RDNA 3.5#38
Nyovelt wants to merge 1 commit into
halo-box:masterfrom
Nyovelt:strix/q6k-mmq-rdna35

Conversation

@Nyovelt

@Nyovelt Nyovelt commented Sep 10, 2026

Copy link
Copy Markdown

Overview

On gfx1151 ggml_cuda_should_use_mmq sends Q6_K matmuls with ne11 > 256 to dequantize + hipBLASLt. That path is
slower than MMQ up to ne11 = 1024 on this GPU: the Q6_K MMQ kernel runs at a flat 16-17 TFLOPS on the fork's RDNA 3.5
tile rows, while the Tensile GEMM drops from 20-22 TFLOPS at K = 5376 to 11-12 TFLOPS for K >= 8192 at ne11 = 512
(the ffn_down shapes of 8B models; PMC: L2 hit rate 68% -> 38%, DRAM fetch 1.2x -> 2.8x the unique bytes once the
per-workgroup f16 weight panel outgrows the 2 MB L2) and the dequantize pass adds a full f16 write + read of every
weight per prefill pass. At ne11 = 2048 the two paths trade places per shape (K = 4096: hipBLASLt 0.85-1.0x of MMQ
time, K >= 12288: MMQ 1.17-1.35x faster), so the gate stops at 1024 rather than going to return true. This PR
raises the Q6_K threshold to ne11 <= 1024 under GGML_CUDA_CC_IS_RDNA3_5; RDNA 3.0 and everything else keep the
existing threshold.

Effect: prefill +8-10% on Q4_K_M / Q5_K_M files (their ffn_down and attn_v tensors are Q6_K), +30% on pure Q6_K files,
up to +50% at -ub 384 where the Tensile path has a hole, no change at -ub 2048 (gate off), no change on files without
Q6_K tensors in the prompt path (Q2_K, Q3_K_M, IQ4_XS, Q4_0, Q8_0, tested), no change to decode (MMVQ path). Measured across 12 GGUFs and three more models (Gemma-4-E4B, Qwen3.6-35B-A3B MoE, Gemma-4-31B:
no change / no change / inconclusive) before this PR; the tables below are the merge-base re-run required here.

Interaction with upstream ggml-org#25940: its Q6_K vec_dot change makes the MMQ side another ~1.25x faster
on gfx1151 (19-20 TFLOPS), which only widens the margin this rule relies on.

Measurements

Hardware: Framework Desktop (AMD Ryzen AI Max+ 395, Radeon 8060S, gfx1151), BIOS 03.03, 128 GB LPDDR5X-8000
        (16 GB VRAM carve-out, ttm.pages_limit=29360128 -> 112 GB GTT), platform_profile=performance,
        power_dpm_force_performance_level=high, CPU governor=performance
OS:       AOSC OS, kernel 7.1.7-aosc-main
ROCm:     10.0.0 (HIP 7.15.0, hipcc clang 23.0.0git), rocm-hipblaslt from the same release
Build:    cmake -G Ninja -DGGML_HIP=ON -DGPU_TARGETS=gfx1151 -DAMDGPU_TARGETS=gfx1151 -DGGML_NATIVE=ON -DCMAKE_BUILD_TYPE=Release
Baseline: halo-box/strix-llama.cpp master 5f851647fe5e (merge-base), built and run in the same session
Change:   5532a6451df6 (this branch), same flags
Models:   Qwen3-8B Q4_K_M / Q6_K / Q8_0 (unsloth), Llama-3.1-8B-Instruct Q4_K_M (bartowski), wikitext-2-raw for perplexity
Method:   llama-bench -ngl 99 -o md, -r 5, baseline and change run back to back; Q4_K_M -p 512 -n 128 is repeated twice
          (pass 1 / pass 2) to show run-to-run drift; -ub sweep 128..2048 at -p 2048 as asked by the guidelines

Baseline:

pass 1: Qwen3-8B Q4_K_M -p 512 -n 128 -r 5

llama-bench -m Qwen3-8B-GGUF/Qwen3-8B-Q4_K_M.gguf -p 512 -n 128 -r 5

model size params backend ngl test t/s
qwen3 8B Q4_K - Medium 4.68 GiB 8.19 B ROCm 99 pp512 1389.90 ± 15.86
qwen3 8B Q4_K - Medium 4.68 GiB 8.19 B ROCm 99 tg128 41.54 ± 0.03

pass 2: Qwen3-8B Q4_K_M -p 512 -n 128 -r 5

llama-bench -m Qwen3-8B-GGUF/Qwen3-8B-Q4_K_M.gguf -p 512 -n 128 -r 5

model size params backend ngl test t/s
qwen3 8B Q4_K - Medium 4.68 GiB 8.19 B ROCm 99 pp512 1396.48 ± 16.83
qwen3 8B Q4_K - Medium 4.68 GiB 8.19 B ROCm 99 tg128 41.55 ± 0.05

Qwen3-8B Q4_K_M ubatch axis -p 2048 -n 0 -ub 128..2048 -r 5

llama-bench -m Qwen3-8B-GGUF/Qwen3-8B-Q4_K_M.gguf -p 2048 -n 0 -ub 128,256,384,512,1024,2048 -r 5

model size params backend ngl n_ubatch test t/s
qwen3 8B Q4_K - Medium 4.68 GiB 8.19 B ROCm 99 128 pp2048 1264.52 ± 1.62
qwen3 8B Q4_K - Medium 4.68 GiB 8.19 B ROCm 99 256 pp2048 1414.76 ± 0.39
qwen3 8B Q4_K - Medium 4.68 GiB 8.19 B ROCm 99 384 pp2048 1261.45 ± 2.67
qwen3 8B Q4_K - Medium 4.68 GiB 8.19 B ROCm 99 512 pp2048 1363.72 ± 3.01
qwen3 8B Q4_K - Medium 4.68 GiB 8.19 B ROCm 99 1024 pp2048 1415.84 ± 4.18
qwen3 8B Q4_K - Medium 4.68 GiB 8.19 B ROCm 99 2048 pp2048 1408.97 ± 4.33

Qwen3-8B Q6_K ubatch axis

llama-bench -m Qwen3-8B-GGUF/Qwen3-8B-Q6_K.gguf -p 2048 -n 0 -ub 128,256,384,512,1024,2048 -r 5

model size params backend ngl n_ubatch test t/s
qwen3 8B Q6_K 6.26 GiB 8.19 B ROCm 99 128 pp2048 936.81 ± 0.32
qwen3 8B Q6_K 6.26 GiB 8.19 B ROCm 99 256 pp2048 1033.63 ± 5.68
qwen3 8B Q6_K 6.26 GiB 8.19 B ROCm 99 384 pp2048 692.45 ± 1.89
qwen3 8B Q6_K 6.26 GiB 8.19 B ROCm 99 512 pp2048 837.37 ± 1.05
qwen3 8B Q6_K 6.26 GiB 8.19 B ROCm 99 1024 pp2048 1000.83 ± 2.83
qwen3 8B Q6_K 6.26 GiB 8.19 B ROCm 99 2048 pp2048 1076.15 ± 5.80

Qwen3-8B Q6_K -p 512 -n 128 -r 5

llama-bench -m Qwen3-8B-GGUF/Qwen3-8B-Q6_K.gguf -p 512 -n 128 -r 5

model size params backend ngl test t/s
qwen3 8B Q6_K 6.26 GiB 8.19 B ROCm 99 pp512 852.39 ± 11.39
qwen3 8B Q6_K 6.26 GiB 8.19 B ROCm 99 tg128 32.43 ± 0.02

Llama-3.1-8B Q4_K_M -p 512 -n 128 -r 5

llama-bench -m Llama-3.1-8B-Instruct-GGUF/Llama-3.1-8B-Instruct-Q4_K_M.gguf -p 512 -n 128 -r 5

model size params backend ngl test t/s
llama 8B Q4_K - Medium 4.58 GiB 8.03 B ROCm 99 pp512 1419.03 ± 15.99
llama 8B Q4_K - Medium 4.58 GiB 8.03 B ROCm 99 tg128 42.32 ± 0.03

Qwen3-8B Q8_0 (no Q6_K tensors: control) -p 512 -n 128 -r 5

llama-bench -m Qwen3-8B-GGUF/Qwen3-8B-Q8_0.gguf -p 512 -n 128 -r 5

model size params backend ngl test t/s
qwen3 8B Q8_0 8.11 GiB 8.19 B ROCm 99 pp512 1779.82 ± 22.94
qwen3 8B Q8_0 8.11 GiB 8.19 B ROCm 99 tg128 27.02 ± 0.01

After:

pass 1: Qwen3-8B Q4_K_M -p 512 -n 128 -r 5

llama-bench -m Qwen3-8B-GGUF/Qwen3-8B-Q4_K_M.gguf -p 512 -n 128 -r 5

model size params backend ngl test t/s
qwen3 8B Q4_K - Medium 4.68 GiB 8.19 B ROCm 99 pp512 1505.56 ± 21.25
qwen3 8B Q4_K - Medium 4.68 GiB 8.19 B ROCm 99 tg128 41.55 ± 0.06

pass 2: Qwen3-8B Q4_K_M -p 512 -n 128 -r 5

llama-bench -m Qwen3-8B-GGUF/Qwen3-8B-Q4_K_M.gguf -p 512 -n 128 -r 5

model size params backend ngl test t/s
qwen3 8B Q4_K - Medium 4.68 GiB 8.19 B ROCm 99 pp512 1508.82 ± 18.05
qwen3 8B Q4_K - Medium 4.68 GiB 8.19 B ROCm 99 tg128 41.55 ± 0.03

Qwen3-8B Q4_K_M ubatch axis -p 2048 -n 0 -ub 128..2048 -r 5

llama-bench -m Qwen3-8B-GGUF/Qwen3-8B-Q4_K_M.gguf -p 2048 -n 0 -ub 128,256,384,512,1024,2048 -r 5

model size params backend ngl n_ubatch test t/s
qwen3 8B Q4_K - Medium 4.68 GiB 8.19 B ROCm 99 128 pp2048 1259.95 ± 1.31
qwen3 8B Q4_K - Medium 4.68 GiB 8.19 B ROCm 99 256 pp2048 1410.13 ± 1.26
qwen3 8B Q4_K - Medium 4.68 GiB 8.19 B ROCm 99 384 pp2048 1441.08 ± 3.99
qwen3 8B Q4_K - Medium 4.68 GiB 8.19 B ROCm 99 512 pp2048 1456.31 ± 2.36
qwen3 8B Q4_K - Medium 4.68 GiB 8.19 B ROCm 99 1024 pp2048 1472.21 ± 1.98
qwen3 8B Q4_K - Medium 4.68 GiB 8.19 B ROCm 99 2048 pp2048 1407.58 ± 5.34

Qwen3-8B Q6_K ubatch axis

llama-bench -m Qwen3-8B-GGUF/Qwen3-8B-Q6_K.gguf -p 2048 -n 0 -ub 128,256,384,512,1024,2048 -r 5

model size params backend ngl n_ubatch test t/s
qwen3 8B Q6_K 6.26 GiB 8.19 B ROCm 99 128 pp2048 935.31 ± 0.04
qwen3 8B Q6_K 6.26 GiB 8.19 B ROCm 99 256 pp2048 1031.20 ± 6.37
qwen3 8B Q6_K 6.26 GiB 8.19 B ROCm 99 384 pp2048 1053.68 ± 1.84
qwen3 8B Q6_K 6.26 GiB 8.19 B ROCm 99 512 pp2048 1074.83 ± 0.39
qwen3 8B Q6_K 6.26 GiB 8.19 B ROCm 99 1024 pp2048 1082.85 ± 0.56
qwen3 8B Q6_K 6.26 GiB 8.19 B ROCm 99 2048 pp2048 1066.82 ± 5.70

Qwen3-8B Q6_K -p 512 -n 128 -r 5

llama-bench -m Qwen3-8B-GGUF/Qwen3-8B-Q6_K.gguf -p 512 -n 128 -r 5

model size params backend ngl test t/s
qwen3 8B Q6_K 6.26 GiB 8.19 B ROCm 99 pp512 1115.56 ± 7.96
qwen3 8B Q6_K 6.26 GiB 8.19 B ROCm 99 tg128 32.47 ± 0.01

Llama-3.1-8B Q4_K_M -p 512 -n 128 -r 5

llama-bench -m Llama-3.1-8B-Instruct-GGUF/Llama-3.1-8B-Instruct-Q4_K_M.gguf -p 512 -n 128 -r 5

model size params backend ngl test t/s
llama 8B Q4_K - Medium 4.58 GiB 8.03 B ROCm 99 pp512 1559.45 ± 19.16
llama 8B Q4_K - Medium 4.58 GiB 8.03 B ROCm 99 tg128 42.32 ± 0.03

Qwen3-8B Q8_0 (no Q6_K tensors: control) -p 512 -n 128 -r 5

llama-bench -m Qwen3-8B-GGUF/Qwen3-8B-Q8_0.gguf -p 512 -n 128 -r 5

model size params backend ngl test t/s
qwen3 8B Q8_0 8.11 GiB 8.19 B ROCm 99 pp512 1767.00 ± 20.82
qwen3 8B Q8_0 8.11 GiB 8.19 B ROCm 99 tg128 27.01 ± 0.01

Correctness:

  • test-backend-ops test -b ROCm0 -o MUL_MAT,MUL_MAT_ID on the change build:
14493/14493 tests passed
  Backend ROCm0: OK
  • llama-perplexity -f wiki.test.raw -c 512 -b 512 -ub 512 --chunks 32 -ngl 99 (this change only moves prompt-sized Q6_K matmuls from hipBLASLt f16 to MMQ int8, so PPL is the oracle):
file baseline after
Qwen3-8B-Q4_K_M 9.0263 +/- 0.30832 9.0030 +/- 0.30701
Qwen3-8B-Q6_K 8.8192 +/- 0.29939 8.8085 +/- 0.29892

Additional information

  • What would let this be revisited: a hipBLASLt / Tensile library that keeps its K >= 8192 efficiency on gfx1151, or
    an RDNA 3.5 Q6_K MMQ regression. A K-aware gate (MMQ for K >= 12288 at any ne11) would add another +17-35% on the
    ffn_down shapes at -ub 2048, but ggml_cuda_should_use_mmq does not receive K today; left as a follow-up.
  • The first protocol run of this branch used return true; its -ub 2048 row for the pure Q6_K file was 2.7% below
    baseline (1063.6 vs 1093.6 t/s), which is why the gate was lowered to 1024 and everything re-run. That log is
    kept as logs/strixpr-20260910-run1-returntrue.log in the research repo. The decision data (kernel traces, PMC, K-sweeps) is in the research notes linked
    from the branch description; happy to paste more here.
  • Same-binary A/A runs on this box show +/-1% within-batch drift; ratios below 1.02 should be read as noise.

Requirements

  • I have read and agree with the contributing guidelines
  • This change is Strix Halo specific, or justified by measurements on Strix Halo. General llama.cpp improvements
    belong in halo-box/llama.cpp instead
  • AI usage disclosure: AGENT-AUTHORED. Claude (Claude Code) found the routing gap from kernel traces, wrote the
    5-line change, ran the interleaved A/B harness and this PR's benchmark protocol, and wrote this description. The
    owner reviewed the change and the numbers.
  • What was NOT verified: other RDNA 3.5 parts (gfx1150), Windows, HIP_LAUNCH_BLOCKING=1; CDNA and RDNA 4 are not
    affected by the gate but were not built or run; the Vulkan backend is untouched.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CzgPbiT4PgFRYgLXRob86e

On gfx1151 the Q6_K MMQ kernel runs at a flat 16-17 TFLOPS while the
dequantize + hipBLASLt path drops to 11-12 TFLOPS once K >= 8192 (the
ffn_down shapes of 8B models) and pays a full f16 dequantize round trip
per prefill pass. At ne11 = 2048 the two paths trade places per shape
(K = 4096 favours hipBLASLt, K >= 12288 favours MMQ), so the gate stops
at 1024. Keep RDNA 3.0 and other targets on the existing threshold.

Assisted-by: Claude
Copilot AI lite review requested due to automatic review settings September 10, 2026 05:04

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

The functional change is narrowly scoped to RDNA 3.5 Q6_K routing and appears consistent with existing architecture-gated heuristics; only a minor inline-comment maintainability tweak was noted.

Pull request overview

This PR adjusts the HIP/CUDA MMQ routing heuristic for AMD RDNA 3.5 (gfx1151) so Q6_K matmuls use the MMQ kernel for larger prompt-side column counts (up to ne11 <= 1024), matching the Strix Halo performance measurements described in the PR.

Changes:

  • Extend the GGML_TYPE_Q6_K MMQ eligibility threshold to ne11 <= 1024 specifically on GGML_CUDA_CC_IS_RDNA3_5(cc).
  • Keep existing thresholds unchanged for RDNA 3.0 and all other architectures.
File summaries
File Description
ggml/src/ggml-cuda/mmq.cu Updates ggml_cuda_should_use_mmq() to route RDNA 3.5 Q6_K matmuls through MMQ up to ne11 = 1024.
Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread ggml/src/ggml-cuda/mmq.cu
Comment on lines +556 to +557
// RDNA 3.5 (gfx1151): dequantize + hipBLASLt loses to MMQ up to ne11 = 1024; at 2048 the two
// paths trade places per shape (K = 4096 favours hipBLASLt, K >= 12288 favours MMQ), see PR.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants