Skip to content

opencl: add q5_K gemm and gemv kernels for Adreno#21595

Merged
max-krasnyansky merged 1 commit into
ggml-org:masterfrom
qualcomm:sq/q5_k-adreno
Apr 16, 2026
Merged

opencl: add q5_K gemm and gemv kernels for Adreno#21595
max-krasnyansky merged 1 commit into
ggml-org:masterfrom
qualcomm:sq/q5_k-adreno

Conversation

@shaofeiqi

Copy link
Copy Markdown
Contributor

Overview

Add Q5_K GEMM and GEMV kernels to the Adreno backend to improve performance for Q5_K quantized models.

Additional information

With Qwen3.5-9B-Q5_K_M.gguf on 8 elite gen 5:

master,

common_perf_print: prompt eval time =    7754.19 ms /    89 tokens (   87.13 ms per token,    11.48 tokens per second)
common_perf_print:        eval time =   54689.77 ms /   137 runs   (  399.20 ms per token,     2.51 tokens per second) 

this PR,

common_perf_print: prompt eval time =    1601.59 ms /    89 tokens (   18.00 ms per token,    55.57 tokens per second)
common_perf_print:        eval time =   26400.97 ms /   126 runs   (  209.53 ms per token,     4.77 tokens per second)

Requirements

@shaofeiqi shaofeiqi requested a review from a team as a code owner April 8, 2026 00:01
@github-actions github-actions Bot added ggml changes relating to the ggml tensor library for machine learning OpenCL Issues specific to the OpenCL backend labels Apr 8, 2026
@lhez lhez requested a review from max-krasnyansky April 16, 2026 19:02

@max-krasnyansky max-krasnyansky left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice to see Q5_K. Will get started on the Hexagon version too :)

@max-krasnyansky max-krasnyansky merged commit e45dbde into ggml-org:master Apr 16, 2026
87 of 89 checks passed
cnsiva pushed a commit to saas-home/llama.cpp that referenced this pull request Apr 17, 2026
samuraieng pushed a commit to samuraieng/llama.cpp that referenced this pull request Apr 19, 2026
mengqin pushed a commit to mengqin/llama.cpp that referenced this pull request Apr 20, 2026
ArberSephirotheca pushed a commit to ArberSephirotheca/llama.cpp that referenced this pull request Apr 21, 2026
arthw pushed a commit to arthw/llama.cpp that referenced this pull request Apr 23, 2026
ljubomirj pushed a commit to ljubomirj/llama.cpp that referenced this pull request May 6, 2026
my-other-github-account pushed a commit to my-other-github-account/llama.cpp that referenced this pull request May 15, 2026
my-other-github-account pushed a commit to my-other-github-account/llama.cpp that referenced this pull request May 15, 2026
fewtarius pushed a commit to fewtarius/CachyLLama that referenced this pull request May 30, 2026
wanghqc added a commit to qualcomm/llama.cpp that referenced this pull request Jun 11, 2026
a2366b5 sent all large-N (n_tokens >= 512) Q5_K mul_mats to CPU on the
premise that Q5_K has no Adreno GEMM and therefore always takes the GEMV that
corrupts large-batch prefill. That premise was wrong: Q5_K has had a
trans-weight GEMM + GEMV since PR ggml-org#21595 (e45dbde), fully wired through
ggml_cl_mul_mat_q5_K_f32_adreno and the set_tensor noshuffle convert. Q5_K
weights that pass use_adreno_kernels (dims >= 512) already dispatch to that
GEMM at prefill; the GEMV path is only reached by small/odd-shaped projections.

Verified the GEMM is correct at large N: greedy generation over a 720-token
prompt on Qwen3.5-0.8B (Q5_K SSM in/out proj) is coherent and matches the CPU
reference (modulo expected FP drift in the tail). The garbage batched perplexity
is a separate head_dim>=256 intermediate-logit issue that persists with the CPU
fallback too and does not affect generation.

Add Q5_K to type_has_gemm so large-N Q5_K weights stay on the GPU GEMM instead
of falling back to CPU; small/odd Q5_K projections still fall back (they would
take the buggy GEMV). Removes the per-layer GPU->CPU->GPU round-trip the fallback
forced on the SSM projections. Clean serial A/B on Qwen3.5-0.8B (fa=1, ngl=99,
-r 3): pp1024 1275->1381 (+8.3%), pp4096 957->1070 (+11.8%), pp4096@d8192
453->490 (+8.2%). Decode and N<512 unaffected.
wanghqc added a commit to qualcomm/llama.cpp that referenced this pull request Jun 15, 2026
a2366b5 sent all large-N (n_tokens >= 512) Q5_K mul_mats to CPU on the
premise that Q5_K has no Adreno GEMM and therefore always takes the GEMV that
corrupts large-batch prefill. That premise was wrong: Q5_K has had a
trans-weight GEMM + GEMV since PR ggml-org#21595 (e45dbde), fully wired through
ggml_cl_mul_mat_q5_K_f32_adreno and the set_tensor noshuffle convert. Q5_K
weights that pass use_adreno_kernels (dims >= 512) already dispatch to that
GEMM at prefill; the GEMV path is only reached by small/odd-shaped projections.

Verified the GEMM is correct at large N: greedy generation over a 720-token
prompt on Qwen3.5-0.8B (Q5_K SSM in/out proj) is coherent and matches the CPU
reference (modulo expected FP drift in the tail). The garbage batched perplexity
is a separate head_dim>=256 intermediate-logit issue that persists with the CPU
fallback too and does not affect generation.

Add Q5_K to type_has_gemm so large-N Q5_K weights stay on the GPU GEMM instead
of falling back to CPU; small/odd Q5_K projections still fall back (they would
take the buggy GEMV). Removes the per-layer GPU->CPU->GPU round-trip the fallback
forced on the SSM projections. Clean serial A/B on Qwen3.5-0.8B (fa=1, ngl=99,
-r 3): pp1024 1275->1381 (+8.3%), pp4096 957->1070 (+11.8%), pp4096@d8192
453->490 (+8.2%). Decode and N<512 unaffected.
wanghqc added a commit to qualcomm/llama.cpp that referenced this pull request Jul 2, 2026
a2366b5 sent all large-N (n_tokens >= 512) Q5_K mul_mats to CPU on the
premise that Q5_K has no Adreno GEMM and therefore always takes the GEMV that
corrupts large-batch prefill. That premise was wrong: Q5_K has had a
trans-weight GEMM + GEMV since PR ggml-org#21595 (e45dbde), fully wired through
ggml_cl_mul_mat_q5_K_f32_adreno and the set_tensor noshuffle convert. Q5_K
weights that pass use_adreno_kernels (dims >= 512) already dispatch to that
GEMM at prefill; the GEMV path is only reached by small/odd-shaped projections.

Verified the GEMM is correct at large N: greedy generation over a 720-token
prompt on Qwen3.5-0.8B (Q5_K SSM in/out proj) is coherent and matches the CPU
reference (modulo expected FP drift in the tail). The garbage batched perplexity
is a separate head_dim>=256 intermediate-logit issue that persists with the CPU
fallback too and does not affect generation.

Add Q5_K to type_has_gemm so large-N Q5_K weights stay on the GPU GEMM instead
of falling back to CPU; small/odd Q5_K projections still fall back (they would
take the buggy GEMV). Removes the per-layer GPU->CPU->GPU round-trip the fallback
forced on the SSM projections. Clean serial A/B on Qwen3.5-0.8B (fa=1, ngl=99,
-r 3): pp1024 1275->1381 (+8.3%), pp4096 957->1070 (+11.8%), pp4096@d8192
453->490 (+8.2%). Decode and N<512 unaffected.
wanghqc added a commit to qualcomm/llama.cpp that referenced this pull request Jul 2, 2026
a2366b5 sent all large-N (n_tokens >= 512) Q5_K mul_mats to CPU on the
premise that Q5_K has no Adreno GEMM and therefore always takes the GEMV that
corrupts large-batch prefill. That premise was wrong: Q5_K has had a
trans-weight GEMM + GEMV since PR ggml-org#21595 (e45dbde), fully wired through
ggml_cl_mul_mat_q5_K_f32_adreno and the set_tensor noshuffle convert. Q5_K
weights that pass use_adreno_kernels (dims >= 512) already dispatch to that
GEMM at prefill; the GEMV path is only reached by small/odd-shaped projections.

Verified the GEMM is correct at large N: greedy generation over a 720-token
prompt on Qwen3.5-0.8B (Q5_K SSM in/out proj) is coherent and matches the CPU
reference (modulo expected FP drift in the tail). The garbage batched perplexity
is a separate head_dim>=256 intermediate-logit issue that persists with the CPU
fallback too and does not affect generation.

Add Q5_K to type_has_gemm so large-N Q5_K weights stay on the GPU GEMM instead
of falling back to CPU; small/odd Q5_K projections still fall back (they would
take the buggy GEMV). Removes the per-layer GPU->CPU->GPU round-trip the fallback
forced on the SSM projections. Clean serial A/B on Qwen3.5-0.8B (fa=1, ngl=99,
-r 3): pp1024 1275->1381 (+8.3%), pp4096 957->1070 (+11.8%), pp4096@d8192
453->490 (+8.2%). Decode and N<512 unaffected.
wanghqc added a commit to qualcomm/llama.cpp that referenced this pull request Jul 8, 2026
a2366b5 sent all large-N (n_tokens >= 512) Q5_K mul_mats to CPU on the
premise that Q5_K has no Adreno GEMM and therefore always takes the GEMV that
corrupts large-batch prefill. That premise was wrong: Q5_K has had a
trans-weight GEMM + GEMV since PR ggml-org#21595 (e45dbde), fully wired through
ggml_cl_mul_mat_q5_K_f32_adreno and the set_tensor noshuffle convert. Q5_K
weights that pass use_adreno_kernels (dims >= 512) already dispatch to that
GEMM at prefill; the GEMV path is only reached by small/odd-shaped projections.

Verified the GEMM is correct at large N: greedy generation over a 720-token
prompt on Qwen3.5-0.8B (Q5_K SSM in/out proj) is coherent and matches the CPU
reference (modulo expected FP drift in the tail). The garbage batched perplexity
is a separate head_dim>=256 intermediate-logit issue that persists with the CPU
fallback too and does not affect generation.

Add Q5_K to type_has_gemm so large-N Q5_K weights stay on the GPU GEMM instead
of falling back to CPU; small/odd Q5_K projections still fall back (they would
take the buggy GEMV). Removes the per-layer GPU->CPU->GPU round-trip the fallback
forced on the SSM projections. Clean serial A/B on Qwen3.5-0.8B (fa=1, ngl=99,
-r 3): pp1024 1275->1381 (+8.3%), pp4096 957->1070 (+11.8%), pp4096@d8192
453->490 (+8.2%). Decode and N<512 unaffected.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ggml changes relating to the ggml tensor library for machine learning OpenCL Issues specific to the OpenCL backend

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants