Repository navigation
Eval bug: CUDA decode+prefill collapse at deep KV position on qwen35 hybrid (~5.5x tg, ~21x pp at d154855) #29172
Description
System
- OS: Windows 11 (x64)
- GPU: NVIDIA GeForce RTX 5060 Ti 16GB (16283 MiB, compute capability 12.0 Blackwell, sm_120)
- Driver: 616.92, CUDA 13.4 runtime
- CPU: AMD Ryzen 5 7500F (6C/12T)
- RAM: 16GB DDR5-5600 single stick
- Build: prebuilt
llama-b11047-bin-win-cuda-13.4-x64.zip+ matching cudart (upstream release, not self-built) - Version string:
version: 0.3.0-dev (build 11047)— exact string from--versionbelow
Configuration
llama-bench.exe -m Ternary-Bonsai-2-27B-PTQ1_0.gguf -ngl 99 -fa on -p 512 -n 32 -r 1 -o md -d <depth>Model: prism-ml/Ternary-Bonsai-2-27B-gguf, file Ternary-Bonsai-2-27B-PTQ1_0.gguf (5.95 GB, PTQ1_0 ternary, arch=qwen35, 64 blocks, hybrid attention ~75% linear, SHA256 53107f53…fe33ee3 verified)
Note: this is a ternary-weight model, but the symptom below is in the backend decode path (identical shape to dense-model reports #27623/#27734), not in weight dequantization.
The Issue
Decode (and at depth, also prefill) throughput collapses once the KV position passed in via -d exceeds roughly 150K tokens, on an otherwise healthy fully-GPU-resident run. Short-context numbers on the same binary/model/GPU are normal.
llama-bench -p 512 -n 32 -r 1 (engine-internal timings, not wall clock):
| test | t/s |
|---|---|
| pp512 (d0) | 464.81 |
| tg32 (d0) | 44.68 |
| pp512 @ d154855 | 21.87 |
| tg32 @ d154855 | 8.10 |
That is a ~21x prefill collapse and ~5.5x decode collapse at depth, with exit code 0 (no error, no OOM, no CPU fallback lines). The -d 154855 run took ~1h20m wall, all of it in prompt processing of the synthetic depth prefix.
Same-model CLI spot checks agree: -c 154855 short prompt gives pp ~153 / tg ~42, while -c 262144 gives pp ~44 / tg ~9.
Related control: llama-bench -fa off -d 154855 fails in ~7s at context creation (non-FA path must materialize the full attention matrix); -fa off -d 32768 works (pp 314 / tg 29); -fa off at d0 matches -fa on (pp 462 / tg 43.9). So FA tiled kernels are required at depth, and the collapse happens within the FA path.
Suspected Area
Decode-path attention over long KV for hybrid linear/full-attention models (qwen35-family here: 64 blocks, ~75% linear). Possibly a fallback/slow kernel engaged past some KV-extent threshold, or a memory-latency-bound matvec regime (per #26581's ~21-25ns/KV/attention-layer constant, which is backend-invariant and also points at decode-attention kernels rather than bandwidth).
Two candidate mechanisms I have already ruled out on this machine, with evidence:
- Vulkan-style suballocation fragmentation (Vulkan: ~78% decode throughput cliff at 131072 context — suballocation fragmentation; fixed via GGML_VK_SUBALLOCATION_BLOCK_SIZE=4 GiB #27734): does not apply to CUDA. The CUDA backend uses
ggml_cuda_pool_vmm(contiguous 32GB virtual reservation viacuMemAddressReserve, on-demand physical mapping, LIFO free) on this card (VMM: yesin init log). There is no suballocation block splitting to tune, and noGGML_CUDA_*pool-size knob exists in the binary (all 14GGML_CUDA_*env strings enumerated — none pool-related). - FA VEC→MMA kernel switch at K>=8192 (
fattn.cu:617,gqa_ratio > 4 && K->ne[1] >= 8192): exists in source, but is 19x below the observed 155K cliff and cannot explain it directly.
What I have not done: Nsight/ncu profiling of the deep-position decode kernels (no CUDA toolkit profiler on this box), so I cannot say whether the time goes to a specific fallback kernel, TLB/page-table effects, or latency-bound matvecs. Happy to run any diagnostic build/flags a maintainer suggests — the model file and repro are cheap (modulo the ~80min deep bench run).
Relationship to Existing Issues
- Qwen3.8-27B (hybrid Gated DeltaNet): decode throughput collapses ~25x at context positions >~80K while prompt processing stays fast #27623 (CUDA + Qwen3.8, ~25x decode collapse at 91K): closest symptom match, but that reporter retracted (metric included prefill time); my numbers above are engine-internal
llama-benchtimings, not wall clock. Also their pp stayed fast while mine collapses too — possibly a different (or deeper) threshold of the same family. - Vulkan: ~78% decode throughput cliff at 131072 context — suballocation fragmentation; fixed via GGML_VK_SUBALLOCATION_BLOCK_SIZE=4 GiB #27734 (Vulkan suballocation cliff at 131072): same model family and same depth neighborhood, but Vulkan-specific mechanism (see above for why it doesn't transfer to CUDA).
- Performance: decode attention is memory-latency-bound on Intel Xe2 (Arc Pro B70) — constant ~21-25 ns per KV position per layer, identical on Vulkan and SYCL #26581 (Xe2 memory-latency-bound decode attention): different vendor, but the only report with a backend-invariant per-KV-position constant — most compatible with my dmon observation (SM 1-2%, mem ~40%: neither compute nor bandwidth saturated while time is spent).
- Eval bug: Qwen3.8-27B decode throughput degrades ~30% within a single generation on CUDA #27444 (closed, build-env
nsm=1misread): not applicable — prebuilt official binary, and short-context numbers are healthy (a brokennsmwould slow everything, not just deep positions).
Steps to Reproduce
- Download
Ternary-Bonsai-2-27B-PTQ1_0.gguffromprism-ml/Ternary-Bonsai-2-27B-gguf. - Official CUDA build is enough (no special flags):
llama-bench.exe -m Ternary-Bonsai-2-27B-PTQ1_0.gguf -ngl 99 -fa on -p 512 -n 32 -r 1 -o md llama-bench.exe -m Ternary-Bonsai-2-27B-PTQ1_0.gguf -ngl 99 -fa on -p 512 -n 32 -r 1 -o md -d 154855
- Compare the
tg32rows (44.68 vs 8.10). Expect ~80min wall for the deep run (all prefill).
Expected: modest depth decay (cf. 2×3090 non-repro in #27623: 40.92 → 28.68 from d0 to d131072).
Actual: ~5.5x decode and ~21x prefill collapse at d154855.
Logs
Logs
$ llama-bench.exe -m Ternary-Bonsai-2-27B-PTQ1_0.gguf -ngl 99 -fa on -p 512 -n 32 -r 1 -o md
| qwen35 27B PTQ1_0 - 1.75 bpw ternary (group 128) | 5.53 GiB | 26.90 B | CUDA | 99 | 1 | pp512 | 464.81 ± 0.00 |
| qwen35 27B PTQ1_0 - 1.75 bpw ternary (group 128) | 5.53 GiB | 26.90 B | CUDA | 99 | 1 | tg32 | 44.68 ± 0.00 |
build: d8f26eec7 (10683)
$ llama-bench.exe [same] -d 154855
| qwen35 27B PTQ1_0 - 1.75 bpw ternary (group 128) | 5.53 GiB | 26.90 B | CUDA | 99 | 1 | pp512 @ d154855 | 21.87 ± 0.00 |
| qwen35 27B PTQ1_0 - 1.75 bpw ternary (group 128) | 5.53 GiB | 26.90 B | CUDA | 99 | 1 | tg32 @ d154855 | 8.10 ± 0.00 |
build: d8f26eec7 (10683)Note: binary reports build 10683 (PrismML fork, required for ternary weights — stock builds reject PQ2_0/PTQ1_0 files). The fork is at a 9/9 upstream base; the decode path exercised here is upstream code. Happy to re-run on a stock build with a dense qwen35-family model if a maintainer considers the ternary aspect relevant — but the symptom shape matches dense-model reports #27623/#27734 too closely for the weights to be the driver.
dmon snapshot during deep decode (sm 1-2%, mem ~40%, pclk ~400MHz both sides — compute, bandwidth and clocks are not the differentiator; time is spent elsewhere).
Disclosure: this report was drafted with AI assistance (Muse Spark 1.3). Every number above is a measured value from the listed hardware (the deep bench run took ~80min, exit code 0); no AI-generated code is included. The hypothesis section is labeled as such — the VMM/FA-switch analysis is from reading the b11047 source, the latency-bound pointer is from #26581, neither is claimed as a diagnosis.
Activity
numsu commentedon Sep 29, 2026
Reproduced on another Blackwell system.
Setup
87268f775(build 10746)Ternary-Bonsai-2-27B-PTQ1_0.ggufAt shallow context performance is normal:
At larger context depth, prompt processing collapses to roughly 20–27 t/s:
prompt processing, n_tokens = 512, t = 19.15 s / 26.74 tokens per secondA
llama-bench -d 70000run also exhibits the severe slowdown.159753a52 commentedon Sep 30, 2026
A compute-only sanity check says this is a real kernel problem, not attention FLOPs catching up.
Bonsai 2 27B has the Qwen3.8 27B layout: 64 layers, 16 with full attention, 48 Gated DeltaNet. For pp512 at depth d, only those 16 layers grow with d. Counting FLOPs per 512-token batch on an RTX 5060 Ti (94.9 FP16 tensor TFLOPS on NVIDIA's spec page):
Your d0 is 464.81 t/s, so compute alone predicts roughly 210 t/s at d154855. You measured 21.87, about 10x below that, and numsu sees the same 20–27 t/s floor on an RTX PRO 1000. That fits the "slow path past some KV extent" theory better than a bandwidth or FLOP limit.
For reference, reading a fresh prompt into an empty cache on this card with Q4_K_M-class kernels, I estimate 7.6–10 s for 8K, 16–21 s for 16K and 33–44 s for 32K for a 27B model of this layout. Your 465 t/s at d0 is about half my ~1,000 t/s estimate, which I'd put down to the PTQ1_0 kernels (not what I calibrated on). The ratios in the table don't depend on that.
These are estimates: tensor throughput times a share fitted on 32 public llama-bench runs (CUDA/ROCm scoreboards in discussions #15013 and #15021, plus PR #25319), all within ±28% of the measured value. Method and calibration table: [Link removed by moderator]/llm-speed-calculator/ (I built it).