Skip to content

ggml-cpu: add opt-in Q2_0 VNNI64 four-row decode - #95

Draft
chris-lee-mc wants to merge 1 commit into
PrismML-Eng:prismfrom
chris-lee-mc:pr/q2-0-vnni64-minimal
Draft

ggml-cpu: add opt-in Q2_0 VNNI64 four-row decode#95
chris-lee-mc wants to merge 1 commit into
PrismML-Eng:prismfrom
chris-lee-mc:pr/q2-0-vnni64-minimal

Conversation

@chris-lee-mc

Copy link
Copy Markdown

Summary

This draft reduces the Prism CPU proposal to the minimal Q2_0 backend change and its evidence:

  • opt-in Phase 9 four-row AVX-512 VNNI decode in ggml-cpu;
  • native Q2_0 storage retained as the fallback;
  • minimal Q2_0 packer contract and implementation;
  • deterministic logits/token parity comparator;
  • concise real-model evidence.

Scope

Kept:

  • ggml/src/ggml-cpu/CMakeLists.txt
  • ggml/src/ggml-cpu/repack.cpp
  • third_party/tbkern/include/tbkern/format.h
  • third_party/tbkern/include/tbkern/q2_pack.h
  • third_party/tbkern/src/q2_pack.c
  • scripts/tbkern_compare.py
  • docs/tbkern/phase9-four-row-vnni64.md
  • docs/tbkern/phase9-prism-evidence.md

Removed from the proposal:

  • Phase 1-8 narrative documents
  • unused dispatch and standalone GEMV sources
  • unrelated public TBKERN GEMV, GEMM, quantization, and arena APIs

Real-weight evidence

Model: Ternary-Bonsai-27B-Q2_0.gguf
Host: Google Cloud C3 highmem-8, Intel Xeon Platinum 8481C, 4 physical cores plus SMT, 8 ggml threads
Command: llama-bench -m MODEL -p 0 -n 16 -t 8 -ngl 0 -b 32 -ub 32

Baseline is unmodified Prism on the same model, host, command, and thread count:

Route Run 1 Run 2 Run 3
Native Prism 1.09 tok/s 1.09 tok/s 1.09 tok/s
Phase 9 four-row VNNI64 1.52 tok/s 1.53 tok/s 1.53 tok/s

The historical matched set shows approximately a 40% target-decode improvement.

Correctness was bit-identical on the real model:

  • logits SHA-256: 65d581397ae42288fe1115e7fa434589700cacd98edc67a750c0fba1765062f2
  • generated-token SHA-256: 7a7748eacf971049271242b9d921628019d6c44698574e9301da9b8c88026381
  • NMSE: 0
  • top-1 mismatches: 0
  • one-chunk PPL: 1.0645 +/- 0.03006

The selector remains opt-in because the recorded perplexity workload was slower even though PPL matched. Attention, norms, RoPE, softmax, GDN recurrence/convolution, KV cache, sampling, scheduling, and GPU execution remain Prism-native.

Validation

  • based on Prism prism at 7529fda;
  • git diff --check passes;
  • scripts/tbkern_compare.py parses successfully;
  • current Windows environment lacks CMake, GCC/Clang, and llama-bench, so a fresh rebuild of this cleanup commit is still required before marking this draft ready for review.

Raw model files and logs are not included.

@github-actions github-actions Bot added documentation Improvements or additions to documentation ggml labels Jul 20, 2026
@khosravipasha
khosravipasha requested a balanced review from Copilot August 26, 2026 01:55
@khosravipasha

Copy link
Copy Markdown
Collaborator

Hi Thanks for the PR, is that something we can upstream to main llama.cpp
Doing a big migration to newer llama.cpp in our prism-v7 branch, then going back to old PRs

This seems in draft mode did we mean to merge it? And also has lots of extra files that probably wont want to merge.

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.

Pull request overview

Adds an opt-in Q2_0 packed-cache decode path for AVX-512 VNNI CPU inference.

Changes:

  • Adds Q2_0 packing formats and implementation.
  • Integrates scalar and SIMD decode routes into CPU repacking.
  • Adds parity tooling and performance evidence.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
ggml/src/ggml-cpu/CMakeLists.txt Builds the packing source.
ggml/src/ggml-cpu/repack.cpp Implements repacking and decode routes.
third_party/tbkern/include/tbkern/format.h Defines packed Q2_0 formats.
third_party/tbkern/include/tbkern/q2_pack.h Declares the packing API.
third_party/tbkern/src/q2_pack.c Implements Q2_0 packing.
scripts/tbkern_compare.py Compares parity artifacts.
docs/tbkern/phase9-four-row-vnni64.md Documents four-row decoding.
docs/tbkern/phase9-prism-evidence.md Records validation evidence.

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

target_include_directories(${GGML_CPU_NAME} PRIVATE . ggml-cpu)

# Resolve from the project root inside this function to avoid caller-scope shadowing.
set(TBKERN_ROOT "${CMAKE_SOURCE_DIR}/third_party/tbkern")
Comment on lines +26 to +29
/* Mainline GGUF Q2_0 native block covers 64 weights (QK2_0). PrismML's native
* variant uses group-128 blocks with identical code semantics. All tbkern code
* parameterizes the group size G at runtime; these are the only legal values. */
#define TBK_QK2_0 64 /* mainline GGUF Q2_0 block length */
Comment on lines +6 to +11
* Ground truth: mainline llama.cpp GGML_TYPE_Q2_0 (ggml-common.h / ggml-quants.c).
* See docs/FORMAT.md for the normative spec and bit-exact diagrams.
*
* RULE (docs/CONTEXT.md §Rules): after Phase 0 this header may only be changed
* by the orchestrator. Code against it; do not edit it.
*/
/* Code semantics (2-bit quant code -> ternary/quaternary weight value):
* 00 = -1, 01 = 0, 10 = +1, 11 = +2. value = (code - 1) * scale.
* The unsigned datum u = code = (w + 1) in {0..3} is what the VNNI path feeds
* to vpdpbusd (see docs/FORMAT.md §VNNI). +2 (code 3) is legal Q2_0 but never
@@ -0,0 +1,155 @@
/* tbkern/format.h — FROZEN Phase-0 contract.
Comment on lines +94 to +95
int tbk_pack_from_q2(const uint8_t *gguf_q2_blocks, int M, int K, int G,
tbk_layout_kind layout, tbk_mat *out) {
Comment on lines +4812 to +4813
static bool tbkern_q2_0_enabled() {
return tbkern_q2_0_scalar_enabled() || tbkern_q2_0_avx2_enabled() || tbkern_q2_0_vnni_enabled() || tbkern_q2_0_vnni64_enabled() || tbkern_q2_0_vnni64_4r_enabled();
@chris-lee-mc

Copy link
Copy Markdown
Author

I ran the benchmark again, it seems any performance gains I had were on an earlier version of your main branch here and were superseded after rebasing from main. I ran this again today with this opt-in turned on and performance was worse, so not sure it would be worth merging at this point. Happy to clean it up if you want to keep this opt-in as an option. Thanks for supporting the CPU path for this quantization as it could be useful for batch inference on CPUs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation ggml

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants