Fix determinism leaks in TurboQuant KV cache and WHT state management - #281
Open
giveen wants to merge 3 commits into
Open
Fix determinism leaks in TurboQuant KV cache and WHT state management#281giveen wants to merge 3 commits into
giveen wants to merge 3 commits into
Conversation
Assisted-by: DeepSeek
Assisted-by: Buffy
…ry global Assisted-by: Buffy
|
Vote for this, and it may close #282. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix determinism leaks in TurboQuant KV cache and WHT state management
Branch:
fix/h1-h2-turbo-kv-determinismBase: TurboQuant fork of llama.cpp (commit
27a68cf58)Files changed:
src/llama-kv-cache.cpp,ggml/src/ggml-turbo-quant.c,ggml/src/ggml-cpu/ops.cpp(+38 / -58)Date: 2026-08-08
Models tested:
Qwen3-8B-Q8_0.gguf(PPL/greedy),gemma-4-26B-A4B-it+ MTP draft (Speculative Decoding)Executive Summary
Verdict: NO REGRESSION — proven bit-identical on CPU and GPU, including MTP speculative decoding.
This PR addresses two distinct determinism and thread-safety hazards in the TurboQuant path (+38/-58, net negative). All four validation layers confirm zero regression: full test suite green, CPU bit-identical, GPU bit-identical, and MTP acceptance identical.
(An early GPU "regression" featuring PPL deltas and a
SOFT_MAXcrash was root-caused to a scratch build linking distro CUDA 12.4 libraries instead of the CUDA 13.3 toolkit. When built against identical toolchains, baseline and feature binaries match identically across all benchmarks.)1. Description of Fixes
1.1 H1 — KV cache layer-adaptive policy leak (
src/llama-kv-cache.cpp)Bug: The
TURBO_LAYER_ADAPTIVEmode resolution was implemented as astatic constlambda declared inside the per-layer constructor loop ofllama_kv_cache::llama_kv_cache. Because C++ initializes static locals on first execution, the first cache instance's resolved policy was silently reused by every subsequent cache instance in the process.This impacted core scenarios targeted by this fork:
turbo2-Vdraft cache losing its auto-enabled Boundary V policy).Fix: Hoisted policy resolution to the constructor scope as a per-instance
const int adaptive_mode, computed once against that instance's own environment and types.Design Note: Shared (MTP draft) caches explicitly resolve their own policy from their own types; the mode is not inherited from the parent cache (deliberately distinct from
attn_rot, which does inherit).1.2 H2 — WHT group-size global state (
ggml-turbo-quant.c+ggml-cpu/ops.cpp)Bug: A process-global
int turbo3_cpu_wht_group_sizewas defined inggml-turbo-quant.c(libggml-base) and extern-declared inops.cpp(libggml-cpu). The CPUSET_ROWShandler wrote the WHT group size into this global as a side effect, which theturbo2_0/turbo3_0quantization functions later read.This introduced two primary hazards:
SET_ROWSwrite path executing beforehand, creating a non-thread-safe side channel by design.Fix: Removed the global entirely and replaced it with a pure function
turbo_wht_group_size(k)inside the codec. It derives the group size deterministically from the row length:128 if k % 128 == 0 else 64. Removed theSET_ROWSside-channel write. This selection strictly matches the graph-side inverse-WHT group selection inllama-graph.cpp.2. Validation & Verification
2.1 Unit and Integration Test Gates
ctesttest-tokenizers-ggml-vocabsfailed due to environment LFS fetch issue (unrelated)test-backend-ops/tmp/backend-ops-final.log)test-turbo-quanttest-quantize-fnstest-chat2.2 CPU Determinism (Gold-Standard Gate)
Tested via
llama-perplexitywithQwen3-8B-Q8_0.ggufon CPU (-t 1,--temp 0):2.3 GPU Parity (CUDA 13.3 Toolkit)
Tested via
llama-perplexitywithQwen3-8B-Q8_0.gguf(-ngl 99, 4 chunks):f16 / f16q8_0 / q8_0turbo2 / turbo2turbo3 / turbo3turbo4 / turbo4q8_0 / turbo32.4 MTP / Speculative Decoding
Tested with
gemma-4-26B-A4B-it+ MTP draft (--spec-type draft-mtp,q8_0/turbo2on both caches, 256 tokens):3. Toolchain & Build Requirements
When building scratch binaries for A/B testing on systems with distro-provided CUDA 12.x packages, explicitly pass
-DCUDAToolkit_ROOT=/usr/local/cuda. Failing to pass this flag allows CMake to silently resolve system CUDA 12.4 runtime libraries instead of the CUDA 13.3 toolkit, leading to cuBLAS numerical shifts and potentialSOFT_MAXkernel failure artifacts.4. Diff Summary
src/llama-kv-cache.cpp(+28/-24): Removedstatic const int adaptive_modelambda inside the per-layer loop. Added per-instanceconst int adaptive_moderesolution at constructor top level.ggml/src/ggml-turbo-quant.c(+10/-16): RemovedGGML_API int turbo3_cpu_wht_group_size. Addedstatic int turbo_wht_group_size(int64_t k). Updated quantizers to call pure function.ggml/src/ggml-cpu/ops.cpp(0/-17): Removedextern "C"declaration block andSET_ROWSside-channel global write.AI Assisted: Yes