Skip to content

CUDA: add Q2_0 (ternary, group-64) weight support - #96

Merged
Anbeeld merged 1 commit into
Anbeeld:v0.4.2from
Andgihat:ternary-bonsai-q2_0-v0.4.0
Jul 28, 2026
Merged

CUDA: add Q2_0 (ternary, group-64) weight support#96
Anbeeld merged 1 commit into
Anbeeld:v0.4.2from
Andgihat:ternary-bonsai-q2_0-v0.4.0

Conversation

@Andgihat

@Andgihat Andgihat commented Jul 20, 2026

Copy link
Copy Markdown

What

Adds the CUDA weight path for GGML_TYPE_Q2_0 (the group-64 ternary format, id 42) so ternary GGUFs — e.g. PrismML's Ternary-Bonsai-27B group-64 — run on GPU. v0.4.2 already ships the CPU reference for this type; only the CUDA kernels were missing (the tree wired GGML_TYPE_Q2_0S but not GGML_TYPE_Q2_0).

Provenance

The kernels are ported from upstream ggml-org#25707 ("CUDA: add Q2_0 support", by @khosravipasha), which targets the same group-64 layout. Credit for the kernel design is upstream's. This PR adapts that patch to the v0.4.2 tree so the format works on BeeLlama before ggml-org#25707 merges upstream; it should become redundant once you rebase past that merge.

Changes

  • dequantize.cuh, vecdotq.cuh (vec_dot_q2_0_q8_1), mmq-load-tiles.cuh (load_tiles_q2_0): the (c-1) ∈ {-1,0,+1,+2} symbol mapping over the sequential 2-bit layout.
  • convert.cu, getrows.cu, mmvq.cu, mmq.cu / mmq.cuh, common.cuh type traits, ggml-cuda.cu supports_op: type registration.
  • Per-arch MMQ configs (ampere/cdna/pascal/rdna2/rdna4). Blackwell inherits via the ampere fall-through, so no separate blackwell entry is needed.
  • Template instance mmq-instance-q2_0.cu + generator entry.
  • Scope is the weight path only. Q2_0-as-KV-cache (FlashAttention) is intentionally left out — this format is for weights, and cache-side ternary stays on Q2_0S.

Verification

  • Builds with CUDA 12.8, -DCMAKE_CUDA_ARCHITECTURES=120 (Blackwell / RTX 50-series), -DGGML_CUDA_FORCE_MMQ=ON.
  • Numerical check on a group-64 GGUF: GPU perplexity matches the CPU reference within FP tolerance — 6.7145 (GPU, -ngl 99) vs 6.7143 (CPU, -ngl 0) over 6×512-token chunks — so both the MMVQ (decode) and MMQ (prefill) paths are correct, with no silent divergence.

Happy to adjust naming/structure to your preference, or to hold this if you'd rather wait for the upstream merge.

@Anbeeld

Anbeeld commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Could you please look into bringing it beyond just CUDA? At least Vulkan as it can be compiled on your hardware.

@Andgihat

Copy link
Copy Markdown
Author

Okay, I'll do it today.

@Andgihat

Copy link
Copy Markdown
Author

Done — pushed Vulkan Q2_0 weight support (mirrors the existing Q1_0 path: dequant, get_rows, mul_mat_vec, mul_mat scalar/coopmat/coopmat2, plus type registration). Weight-only, same scope as the CUDA side; cache paths stay on Q2_0S.

Verified on an RTX 5060 Ti (Blackwell): Vulkan -ngl 99 vs CPU -ngl 0 perplexity on a group-64 GGUF match within FP tolerance — 6.6304 vs 6.6259 over 6×512-token chunks, with all 498 q2_0 tensors offloaded to Vulkan0.

@Andgihat

Copy link
Copy Markdown
Author

I hope this is what you wanted.

@crusaderky

crusaderky commented Jul 27, 2026

Copy link
Copy Markdown

Does this PR differ from ggml-org#25707 ?

Q2_0 vulkan was merged into main llamacpp in ggml-org#25430 I suggest to just merge from main instead

@Andgihat

Andgihat commented Jul 27, 2026

Copy link
Copy Markdown
Author

Good catch - you're right, ggml-org#25430 already landed Vulkan Q2_0 in master, and jeffbolznv's version is perf-tuned (rm_kq_int), which mine isn't (I mirrored the Q1_0 path). This PR targets the fork rather than upstream, and ggml-org#25707 is the CUDA side, so they don't overlap directly - but for Vulkan, merging from main is clearly the better route than carrying my port. @Anbeeld, your call on whether a merge-from-master is clean given the diverged KV-quant types, or whether this stays as a stopgap.

@Andgihat

Copy link
Copy Markdown
Author

I'll see what I can do.

@Anbeeld

Anbeeld commented Jul 27, 2026

Copy link
Copy Markdown
Owner

I merged newer upstream into v0.4.2 branch, please take a look if it's sufficient for Q2_0 by itself or there's still something to PR.

@Andgihat

Copy link
Copy Markdown
Author

I merged newer upstream into v0.4.2 branch, please take a look if it's sufficient for Q2_0 by itself or there's still something to PR.

I'll take a look now

@Andgihat

Copy link
Copy Markdown
Author

Now I will rebase to 4.2 and remove the redundant Vulkan stuff. Compiled, everything fits and works with Vulkan, I'll leave only the CUDA part in PR

@Andgihat

Copy link
Copy Markdown
Author

Give me 10 minutes. I'll build a build to check something out.

@Andgihat
Andgihat force-pushed the ternary-bonsai-q2_0-v0.4.0 branch from 4a59da4 to 1f06a2d Compare July 27, 2026 12:09
@Andgihat
Andgihat requested a review from Anbeeld as a code owner July 27, 2026 12:09
@Andgihat
Andgihat changed the base branch from main to v0.4.2 July 27, 2026 12:09
@Andgihat

Copy link
Copy Markdown
Author

Retargeted this PR to v0.4.2 and dropped the Vulkan commit — v0.4.2 already carries Vulkan Q2_0 via the upstream merge (jeffbolznv's ggml-org#25430), and that version is better than my port anyway (it has the tuned mmq path). So this PR is now CUDA-only.

The CUDA commit cherry-picked onto v0.4.2 with zero conflicts. Verified locally on an RTX 5060 Ti (Blackwell sm_120, CUDA 12.8, -DGGML_CUDA_FORCE_MMQ=ON):

  • Builds clean on the new master (615/615).
  • test-backend-ops -o MUL_MAT -b CUDA0: 1180/1180 passed, including all 27 weight-q2_0 MUL_MAT shapes.
  • PPL parity on a group-64 GGUF (Ternary-Bonsai-27B): 6.6197 (CUDA -ngl 99) vs 6.6259 (CPU -ngl 0) over 6×512 chunks — FP tolerance, no silent divergence.

For completeness I also confirmed the v0.4.2 Vulkan Q2_0 runs correctly on the same card (982/982 backend-ops, PPL 6.6304), so both backends are good. Ready for review.

@Anbeeld
Anbeeld merged commit bda6e0b into Anbeeld:v0.4.2 Jul 28, 2026
@Anbeeld

Anbeeld commented Jul 28, 2026

Copy link
Copy Markdown
Owner

There are a few issues remaining, but I'll fix those myself in a follow-up commit.

Anbeeld added a commit that referenced this pull request Jul 28, 2026
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