ggml-meta : split a host-resident KV cache by head - #48
Closed
Piggidragon wants to merge 49 commits into
Closed
Conversation
Assisted-by: OpenAI Codex Assisted-by: Codex
Assisted-by: OpenAI Codex Assisted-by: Codex
Assisted-by: OpenAI Codex Assisted-by: Codex
Assisted-by: OpenAI Codex
Assisted-by: OpenAI Codex
Assisted-by: OpenAI Codex
Assisted-by: OpenAI Codex
Assisted-by: OpenAI Codex Assisted-by: Codex
…v-q8-cpu-cuda-parity kv-cache: preserve accelerator quantization for host KV stores
Assisted-by: OpenAI Codex
Assisted-by: OpenAI Codex
Assisted-by: OpenAI Codex
…hase-peak-shared llama: share target and MTP phase workspaces
Assisted-by: OpenAI Codex
Assisted-by: Codex
Assisted-by: OpenAI Codex
Keep the internal metadata bounds check on configurations that can link private llama symbols while preserving the exported-API rollback test binary on Windows shared builds. Assisted-by: OpenAI Codex
…tp-replay speculative: cap MTP recurrent rollback planes
Assisted-by: OpenAI Codex
Assisted-by: OpenAI Codex
This was referenced Aug 26, 2026
Assisted-by: OpenAI Codex
Assisted-by: OpenAI Codex
…ompact-causal-mask llama : add compact causal attention masks
Assisted-by: OpenAI Codex
…p-compact-causal-mask llama : clean up compact causal masks
Assisted-by: Codex
Assisted-by: OpenAI Codex
Assisted-by: OpenAI Codex
…ive-context-workspace llama : add live-context workspace sizing
Assisted-by: Claude Opus 5
Assisted-by: Claude Opus 5
Assisted-by: Claude Opus 5
Assisted-by: Claude Opus 5
Assisted-by: Claude Opus 5
Assisted-by: Claude Opus 5
Assisted-by: Claude Opus 5
Assisted-by: Claude Opus 5
Assisted-by: Claude Opus 5
Assisted-by: Claude Opus 5
Assisted-by: Claude Opus 5
Assisted-by: Claude Opus 5
Assisted-by: Claude Opus 5
Assisted-by: Claude Opus 5
Preserve the pre-ubatch GDN state in the rollback slot when the whole ubatch can be removed. Keep the full-replay logits as the dirty-context oracle and compare exact Qwen3.5 recurrent checkpoints in the multi-sequence regression. Assisted-by: Codex
Piggidragon
force-pushed
the
fix/tp-host-kv-cache
branch
from
August 28, 2026 20:26
0ecfbb3 to
5d9b5b8
Compare
Assisted-by: OpenAI Codex
Piggidragon
force-pushed
the
fix/tp-host-kv-cache
branch
from
August 28, 2026 20:39
5d9b5b8 to
e6c074c
Compare
Author
|
Superseded by #57, which fixes this for every model instead of one shape and is branched from llama/dev rather than master. |
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.
Fixes
--split-mode tensortogether with--no-kv-offload, which on a GQA modeleither crashes or silently returns wrong output.
Branched from
master(d222767c7); no code frombeellama/*orllama/devisinvolved. It applies unchanged on top of current ggml-org
master(5d5cb4c3a).The defect
With
-sm tensor,ggml-backend-metaasks the model's split-state callback how eachtensor is divided across devices. That question is only asked for tensors outside a
compute buffer:
With
-nkvothe KV cache lives in host memory, so it is not a tensor of the metabackend at all. The scheduler copies it in, and that copy is a leaf in the compute
buffer. It therefore never reaches the callback and falls through to
MIRRORED, whilethe queries stay split by head. Both devices then hold every KV head but only half the
query heads, so
handle_flash_attn_ext'skv_mirroredbranch is taken, and eachdevice's renumbered queries attend the other device's keys.
kv_mirroredis correct where it was written for -- MLA, one KV head, every query headmaps to head 0. It is wrong for any GQA cache with more than one KV head.
Reproducing on pristine upstream
Two GPUs (RTX 4070 + RTX 3060), CUDA, NCCL on.
gemma-4-26B-A4B(n_head16,n_head_kv8, attention only) aborts:llama-completion -m gemma-4-26B-A4B.gguf -ngl 99 -c 4096 -n 64 \ --temp 0 --top-k 1 --seed 1 --no-warmup --jinja -p "..." \ -sm tensor -ts 55,45 -nkvoWhere the query split happens to stay a multiple of the KV head count the assert does
not fire and the output is simply wrong. That is what this looked like before the FA
kernel gained the shape check.
The fix
ggml-backend-meta.cpp-- offer a copied-in compute-buffer leaf to the split-statecallback. Names the callback does not know still answer
MIRRORED, so nothing elsechanges.
llama-model.cpp-- undecorate<backend>#cache_k_l0 (view) (permuted)#0back tocache_k_l0. Only a cache name is undecorated.llama-model.cpp-- a host-resident cache arrives permuted as[head_dim, n_kv, n_head_kv, n_stream], so it splits on axis 2 with one KV head asthe unit rather than on axis 0 with one head's worth of elements.
ggml-backend-meta.cpp-- writing that split is a strided copy, because the headsare interleaved inside each cell rather than laid out end to end.
Testing
gemma-4-26B-A4B-Q?, 2 GPUs,-ts 55,45, greedy, seed 1, sha256 of the generated text:-sm layerf3208b98afd39dcff3208b98afd39dcf-sm layer -nkvof3208b98afd39dcff3208b98afd39dcf-sm tensorf3208b98afd39dcff3208b98afd39dcf-sm tensor -nkvofattn.cu:371)f3208b98afd39dcfQwen3.8-27B-UD-Q5_K_M, same setup, checked for regressions:-sm layer493f41387bec090fand-sm tensor79af072c6bb1e154are unchanged from anunmodified build of the same commit.
Not fixed here
A hybrid model with linear-attention layers still aborts under
-sm tensor -nkvo:Same root cause, different tensor.
--no-kv-offloadalso puts the recurrent state inhost memory, and it reaches the gated-delta-net op not as
cache_s_l<il>but as thegraph tensors
state_predelta-<il>andconv_states_reshaped-<il>, which are computedon the CPU backend and copied in. Those are graph names, not cache names, so the
name-based callback cannot classify them. Keeping the recurrent state on device avoids
it entirely; attention-only models are unaffected.
AI usage disclosure: yes, see the commit trailer.