Skip to content

(AI policy violation) Metal: TurboQuant GPU dequant kernels + host buffer type#21818

Closed
sachmans wants to merge 7 commits into
ggml-org:masterfrom
sachmans:pr-turboquant-metal
Closed

(AI policy violation) Metal: TurboQuant GPU dequant kernels + host buffer type#21818
sachmans wants to merge 7 commits into
ggml-org:masterfrom
sachmans:pr-turboquant-metal

Conversation

@sachmans

Copy link
Copy Markdown

Summary

Adds Metal GPU support for TurboQuant KV cache types (TBQ3_0/TBQ4_0) on Apple Silicon. Two components:

Stage 1: Metal dequant kernels

  • GPU compute kernels for TBQ3_0/TBQ4_0 → F16/F32 conversion via GGML_OP_CPY
  • Performs inverse Householder QR rotation (baked 128×128 matrix) and Lloyd-Max codebook lookup entirely on GPU
  • 4 kernel variants: kernel_cpy_tbq{3,4}_0_{f16,f32}

Stage 2: Metal host buffer type (MTL0_Host)

  • New buffer type backed by shared-storage MTLBuffer that reports is_host = true
  • Tensors allocated here are accessible by both the Metal backend (GPU dequant via CPY) and the CPU backend (SET_ROWS for F32→TBQ quantize)
  • The ggml scheduler routes each op to the appropriate backend automatically
  • Follows the same pattern as CUDA's ggml_backend_cuda_host_buffer_type() (pinned host memory)

Architecture

Token generation:
  Attention scores → SET_ROWS (F32→TBQ quantize) → CPU backend claims this op
  KV read → CPY (TBQ→F16 dequant) → Metal backend claims this op
  Both operate on the SAME tensor in MTL0_Host shared memory

This avoids needing a Metal SET_ROWS (forward rotation + quantize) kernel, which would be significantly more complex.

Benchmark results (Gemma 3 4B Q4_K_M, Mac Studio M3 Ultra)

K cache V cache pp512 (t/s) tg64 (t/s)
f16 f16 2210 126.7
q4_0 f16 2153 117.9
tbq4_0 f16 869 38.6
tbq3_0 f16 938 37.2

Memory (KV cache @ 8K context)

Config KV size vs f16
f16 K+V 1024 MiB 1.00×
tbq4_0 K+V 260 MiB 3.94×
tbq4_0 K + tbq3_0 V 228 MiB 4.49×

Accuracy verification (Gemma 3 4B, greedy decoding)

All configs (f16, tbq4_0, tbq3_0, tbq4_0+tbq4_0) produce correct factual answers ("The three primary colors are red, yellow, and blue") with coherent elaboration. TBQ matches F16 baseline quality.

Files changed

  • ggml/src/ggml-metal/ggml-metal.metal — TBQ dequant kernel implementations
  • ggml/src/ggml-metal/ggml-metal-turboq-rot.h — Baked 128×128 Householder rotation matrix
  • ggml/src/ggml-metal/ggml-metal.cpp — Host buffer type + device callback
  • ggml/src/ggml-metal/ggml-metal-ops.cpp — TBQ CPY dispatch
  • ggml/src/ggml-metal/ggml-metal-device.m — TBQ op whitelist
  • ggml/src/ggml-metal/CMakeLists.txt — Header inclusion
  • src/llama-kv-cache.cpp — Host buft routing for TBQ types

Test plan

  • Build clean on macOS (M3 Ultra)
  • llama-bench speed comparison across f16/q4_0/tbq4_0/tbq3_0
  • KV buffer allocation confirmed on MTL0_Host (not CPU fallback)
  • Generation correctness on Gemma 3 4B (greedy, deterministic)
  • Generation correctness on Llama 3.1 8B (parity with f16 baseline)
  • test-backend-ops for CPY on TBQ types
  • Verify no regression for non-TBQ KV types

Depends on: #21089

🤖 Generated with Claude Code

elusznik and others added 7 commits April 8, 2026 11:28
Replace scalar/AVX2 matrix-vector multiply in TurboQuant rotation
with cblas_sgemv from Apple's Accelerate framework. This uses the
AMX coprocessor on Apple Silicon for the 128x128 dense rotation
matrix multiply during dequantization.

Results on Mac Studio M3 Ultra, Qwen3-32B Q4_K_M:
  TBQ4_0 K + F16 V:  7.40 → 14.00 t/s  (1.89x faster, 86% of F16)
  TBQ4_0 K + TBQ4_0 V:  5.32 → 11.04 t/s  (2.07x faster, 67% of F16)

Quality unchanged (PPL within noise margin).
After inverse rotation, re-normalize the reconstructed unit vector
to unit length before scaling by the original norm. This removes
magnitude bias from codebook quantization error.

Results on Qwen3-32B Q4_K_M (PPL, lower is better):
  TBQ4_0 K+V:       2.751 → 2.733  (+1.3% → +0.6% vs F16)
  TBQ4_0 K+F16 V:   2.733 → 2.724  (+0.6% → +0.3% vs F16)
  TBQ4_0 K+TBQ3_0 V: 2.767 → 2.730  (+1.9% → +0.5% vs F16)

4.5x compression at +0.5% quality loss (TBQ4_0 K + TBQ3_0 V).
Add comprehensive benchmark section covering:
- PPL comparison (F16, Q8_0, Q4_0, TBQ4_0, TBQ3_0)
- Speed benchmarks (18% overhead noted)
- Max context length across 4 models (8B to 72B)
- Usage examples, known limitations, and roadmap
- Link to experimental/qjl-error-correction branch
Stage 1: Metal compute kernels for TBQ3_0/TBQ4_0 → F16/F32 dequant (CPY op).
Applies inverse Householder QR rotation and Lloyd-Max codebook lookup on GPU.
Includes baked 128×128 rotation matrix in ggml-metal-turboq-rot.h.

Stage 2: New Metal "host" buffer type (MTL0_Host) backed by shared-storage
MTLBuffer with is_host=true. KV cache tensors allocated here are accessible
by both Metal backend (GPU dequant via CPY) and CPU backend (SET_ROWS for
F32→TBQ quantize). The ggml scheduler routes each op to the appropriate
backend automatically.

KV cache allocation updated to use host buffer type for TBQ types when
available, falling back to CPU buffer otherwise.

Benchmarks (Gemma 3 4B Q4_K_M, Mac Studio M3 Ultra):
- TBQ4_0+TBQ3_0 K+V: 4.49× KV compression, coherent output verified
- Metal host buft confirmed active (MTL0_Host in load logs)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot added testing Everything test related examples server ggml changes relating to the ggml tensor library for machine learning Apple Metal https://en.wikipedia.org/wiki/Metal_(API) labels Apr 12, 2026
@ggml-gh-bot

ggml-gh-bot Bot commented Apr 12, 2026

Copy link
Copy Markdown

Hi @sachmans, thanks for your contribution!

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

  • 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 2 open PRs.

  • Multiple backend changes in one PR: When adding support for a new model or feature, focus on CPU support only in the initial PR. Add support for other backends like CUDA in follow-up PRs. If you have a good reason to modify multiple backends in one PR, please explain it.

  • AI-generated content: This project does not accept PRs, descriptions or commit messages that are fully or predominantly AI-generated. If you have used AI to assist you in writing code, please make sure to disclose that explicitly.

  • Large PR: Large changes require prior discussion (e.g. an issue or RFC) and maintainers may not be able to review this PR as-is. Consider splitting it into smaller, focused PRs.


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

@ddh0

ddh0 commented Apr 12, 2026

Copy link
Copy Markdown
Contributor

🤖 Generated with Claude Code

This violates the AI Usage Policy as stated in CONTRIBUTING.md:

This project does not accept pull requests that are fully or predominantly AI-generated. AI tools may be utilized solely in an assistive capacity.

@ngxson

ngxson commented Apr 12, 2026

Copy link
Copy Markdown
Collaborator

I believe this account should be banned if they continue to violate project's policy.

@ngxson ngxson changed the title Metal: TurboQuant GPU dequant kernels + host buffer type (AI policy violation) Metal: TurboQuant GPU dequant kernels + host buffer type Apr 13, 2026
@ngxson ngxson closed this Apr 13, 2026
@sachmans sachmans deleted the pr-turboquant-metal branch May 14, 2026 11:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Apple Metal https://en.wikipedia.org/wiki/Metal_(API) examples ggml changes relating to the ggml tensor library for machine learning server testing Everything test related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants