Skip to content

opencl: add q4_0 o4 GEMV for long-vocab lm_head (a7x) - #30658

Draft
EdgeBites wants to merge 1 commit into
ggml-org:masterfrom
EdgeBites:opencl-q4_0-o4-a7x
Draft

EdgeBites wants to merge 1 commit into
ggml-org:masterfrom
EdgeBites:opencl-q4_0-o4-a7x

Conversation

@EdgeBites

Copy link
Copy Markdown

Adds a 4-output-per-work-item (o4) GEMV for q4_0 decode, mirroring the existing q4_K o4 variant, for long-vocab lm_head / embed shapes.

Motivation

The q4_0 decode GEMV for ne01 >= 32768 (lm_head / embed, e.g. 262144 rows on gemma-4) is the worst q4_0 GEMV shape: each work item computes only 2 output rows, so the per-block activation read + subgroup broadcasts are amortized over just 2 rows. The q4_K path already solves this with kernel_gemv_noshuffle_q4_k_f32_o4 ("4-output-per-WI, long-vocab lm_head"); q4_0 had no equivalent.

Change

  • kernel_gemv_noshuffle_q4_0_f32_o4: 4 consecutive output rows per work item as two 2-row pairs (a, b) that share one activation read per k-block. The existing 2-row dequantizeBlockAccum_ns_sgbroadcast_* macros are reused unchanged, so each row's accumulation order — and therefore the result — is byte-identical to the base GEMV.
  • Dispatch: decode only (ne1 == 1), ne01 % 4 == 0 && ne01 >= 32768, default on, opt-out GGML_OPENCL_Q4_0_O4=0. Launch {CEIL_DIV(ne01/4,64)*64, 4, 1}; tail quads past the last row are guarded.

Benchmarks (gemma models, Adreno 740 / SM8550)

llama-bench --device GPUOpenCL -ngl -1 -fa on -p 1 -n 64 -r 2, interleaved A/B (base = same tree without the change):

model base tg64 o4 tg64 delta
gemma-4-E2B q4_0 11.47 12.97 +13.1%
gemma-4-E4B qat Q4_0 7.90 8.71 +10.3%
gemma-3-1b q4_0_s 17.33 17.97 +3.7%
  • Prefill unchanged: E2B pp256 205.4 -> 206.9 (within noise)
  • Greedy 24-token output byte-identical between o4 on/off

Port the q4_K o4 variant (4 outputs per work item, one shared activation
read per k-block) to the q4_0 noshuffle layout. The long-vocab lm_head /
embed GEMV (ne01 >= 32768) is the worst q4_0 decode shape (~34 GB/s on
Adreno 740); 4 rows per WI doubles the bytes in flight per work item and
amortizes the activation read/broadcast across 4 rows.

The two 2-row dequantize/accumulate macros are reused unchanged, so each
row's accumulation order (and thus the result) is byte-identical to the
base GEMV. Default on for ne01 >= 32768; opt-out GGML_OPENCL_Q4_0_O4=0.

tg64, gemma models, Adreno 740 (SM8550):
  gemma-4-E2B q4_0   11.47 -> 12.97  (+13.1%)
  gemma-4-E4B q4_0    7.90 ->  8.71  (+10.3%)
  gemma-3-1b  q4_0   17.33 -> 17.97  (+3.7%)
prefill unchanged (E2B pp256 205.4 -> 206.9); greedy output byte-identical.
@ggml-gh-bot

ggml-gh-bot Bot commented Oct 16, 2026

Copy link
Copy Markdown

Hi @EdgeBites, thanks for your contribution!

Per our contribution guidelines, the automated PR checker found the following issue(s) that need your attention:

  • PR Template not respected: Please respect the template when creating a new pull request. Make sure to fill out all required sections.

  • Multiple open PRs from a new contributor: We limit new contributors (those without a previously merged PR) to 1 open PR at a time. You currently have 3 open PRs.

  • AI-generated content: While code is allowed to be generated by AI, please write the PR description and commit messages on your own without the help of AI.


Please note that maintainers reserve the right to make final decisions on PRs. If you believe there is a mistake, please comment below.

@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 Oct 16, 2026

This branch has not been deployed

No deployments
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.

1 participant