Repository navigation
CUDA illegal memory access after long prefill with q4_0 K/V + FA (prism-b10770, regression from b10709) #346
Description
Build: prism-b10770-6684606 (commit 6684606ac), clean checkout, static
-DGGML_CUDA=ON -DCMAKE_CUDA_ARCHITECTURES=86 -DBUILD_SHARED_LIBS=OFF -DGGML_CUDA_FA_QUANTS=q4_0-q4_0,q8_0-q8_0,f16-f16,bf16-bf16
GPU: NVIDIA GeForce RTX 3070 Laptop GPU (sm_86, 8 GB), driver 595.91.07, CUDA 12.4, Ubuntu Server, GCC 15.2
Model: Ternary-Bonsai-2-27B-PTQ1_0.gguf (sha256 53107f530aa52eb0…)
Command:
llama-server -m Ternary-Bonsai-2-27B-PTQ1_0.gguf --host 127.0.0.1 --port 8081 -ngl 99 -c 65536 -np 1 -fa on -ctk q4_0 -ctv q4_0 --jinja --reasoning-budget 2048 --temp 1.0 --top-p 0.95 --top-k 20 --min-p 0.05 --threads 8
Default -b/-ub, no --spec-*, no drafter/MTP. Env: only CUDA_LAUNCH_BLOCKING=1; no other GGML_CUDA_* / LLAMA_ARG_* set (GGML_CUDA_FA_PREFILL_F16 from #330 is not in this tree).
Repro: single /v1/chat/completions request, needle-in-haystack prompt (code word at the start + repeated filler sentence + question at the end), max_tokens 3000.
| Prompt | ctx-checkpoints | b10709 (9a9394a) |
b10770 (6684606ac) |
|---|---|---|---|
| ~45K tokens | default | correct answer (prefill 271 t/s) | crash right after prefill reaches 100% |
| ~30K tokens | default | — | crash right after prefill reaches 100% |
| ~45K tokens | 0 | — | correct answer (1 run) |
| ~16K tokens | default | — | no crash; 3000 tokens generated, empty content (reasoning budget not applied?) |
With CUDA_LAUNCH_BLOCKING=1, the error surfaces in launch_fattn (fattn-common.cuh:1113) at the
cudaOccupancyMaxActiveBlocksPerMultiprocessor query, i.e. before the FA kernel launches — so the faulting
kernel appears to be one launched just before FA, at the transition from prefill (progress = 1.00) to the first
decode step. Without CUDA_LAUNCH_BLOCKING, the same crash reports at common.cuh:1905 (ggml_cuda_kernel_launch).
Short prompts and tool calling work on b10770, with a large speedup (decode 26 → 43 tok/s, prefill 271 → ~500 t/s).
Suspects from the changelog: #221 (in-place q4_0/q8_0 K/V FA), #312 (reuse evicted checkpoint buffers), #189, #318.
Note: the test server ran without --api-key-file on 127.0.0.1 only; the CORS warning in the log is expected.
Happy to run compute-sanitizer or test a branch if useful.
llama-server log — prism-b10770, 30K prompt, CUDA_LAUNCH_BLOCKING=1
0.01.556.460 I cmn common_param: common_params_print_info: verbosity = 3 (adjust with the `-lv N` CLI arg)
0.01.556.698 W srv llama_server: -----------------
0.01.556.699 W srv llama_server: CORS is set to allow all origins ('*') and no API key is set
0.01.556.699 W srv llama_server: this can be a security risk (cross-origin attacks)
0.01.556.699 W srv llama_server: more info: https://github.com/ggml-org/llama.cpp/pull/25655
0.01.556.699 W srv llama_server: -----------------
0.01.557.943 I srv load_model: loading model '/srv/models/bonsai2-27b/Ternary-Bonsai-2-27B-PTQ1_0.gguf'
0.01.981.219 W common_fit_params: failed to fit params to free device memory: n_gpu_layers already set by user to 99, abort
0.03.288.518 I cmn init: llama threadpool init, n_threads = 8
0.03.404.839 I srv load_model: initializing, n_slots = 1, n_ctx_slot = 65536, kv_unified = 'false'
0.03.408.238 I srv init: chat template supports preserving reasoning, consider enabling it via --reasoning-preserve
0.03.408.245 I srv llama_server: model loaded
0.03.408.247 I srv llama_server: listening on http://127.0.0.1:8081
0.04.038.511 I slot get_availabl: id 0 | task -1 | selected slot by LRU, t_last = -1
0.04.038.566 I slot launch_slot_: id 0 | task 0 | processing task, is_child = 0
0.07.811.803 I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 2090, progress = 0.07, t = 3.77 s / 553.90 tokens per second
0.11.470.420 I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 4138, progress = 0.14, t = 7.43 s / 556.79 tokens per second
0.15.232.956 I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 6186, progress = 0.20, t = 11.19 s / 552.60 tokens per second
0.19.104.219 I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 8234, progress = 0.27, t = 15.07 s / 546.54 tokens per second
0.23.078.968 I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 10282, progress = 0.34, t = 19.04 s / 540.01 tokens per second
0.27.157.551 I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 12330, progress = 0.41, t = 23.12 s / 533.33 tokens per second
0.31.342.018 I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 14378, progress = 0.48, t = 27.30 s / 526.60 tokens per second
0.35.627.988 I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 16426, progress = 0.54, t = 31.59 s / 519.98 tokens per second
0.40.020.194 I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 18474, progress = 0.61, t = 35.98 s / 513.43 tokens per second
0.44.516.624 I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 20522, progress = 0.68, t = 40.48 s / 506.99 tokens per second
0.49.111.772 I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 22570, progress = 0.75, t = 45.07 s / 500.74 tokens per second
0.53.810.091 I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 24618, progress = 0.82, t = 49.77 s / 494.62 tokens per second
0.58.612.051 I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 26666, progress = 0.88, t = 54.57 s / 488.63 tokens per second
1.03.518.469 I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 28714, progress = 0.95, t = 59.48 s / 482.75 tokens per second
1.05.834.579 I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 29668, progress = 0.98, t = 61.80 s / 480.10 tokens per second
1.07.154.954 I slot print_timing: id 0 | task 0 | prompt processing, n_tokens = 30180, progress = 1.00, t = 63.12 s / 478.16 tokens per second
/opt/llama/prism-src/ggml/src/ggml-cuda/ggml-cuda.cu:108: CUDA error
1.07.250.129 E CUDA error: an illegal memory access was encountered
1.07.250.131 E current device: 0, in function launch_fattn at /opt/llama/prism-src/ggml/src/ggml-cuda/template-instances/../fattn-common.cuh:1113
1.07.250.132 E cudaOccupancyMaxActiveBlocksPerMultiprocessor(&max_blocks_per_sm, fattn_kernel, block_dim.x * block_dim.y * block_dim.z, nbytes_shared)
/opt/llama/prism-src/build/bin/llama-server(+0x1973356) [0x5dcfb5d68356]
/opt/llama/prism-src/build/bin/llama-server(+0x197394d) [0x5dcfb5d6894d]
/opt/llama/prism-src/build/bin/llama-server(+0x1973b30) [0x5dcfb5d68b30]
/opt/llama/prism-src/build/bin/llama-server(+0x9ec587) [0x5dcfb4de1587]
/opt/llama/prism-src/build/bin/llama-server(+0x17bcc30) [0x5dcfb5bb1c30]
/opt/llama/prism-src/build/bin/llama-server(+0x17bcfda) [0x5dcfb5bb1fda]
/opt/llama/prism-src/build/bin/llama-server(+0x9fc226) [0x5dcfb4df1226]
/opt/llama/prism-src/build/bin/llama-server(+0xa05305) [0x5dcfb4dfa305]
/opt/llama/prism-src/build/bin/llama-server(+0xa07ece) [0x5dcfb4dfcece]
/opt/llama/prism-src/build/bin/llama-server(+0x199725f) [0x5dcfb5d8c25f]
/opt/llama/prism-src/build/bin/llama-server(+0x689140) [0x5dcfb4a7e140]
/opt/llama/prism-src/build/bin/llama-server(+0x690e39) [0x5dcfb4a85e39]
/opt/llama/prism-src/build/bin/llama-server(+0x696516) [0x5dcfb4a8b516]
/opt/llama/prism-src/build/bin/llama-server(+0x697d52) [0x5dcfb4a8cd52]
/opt/llama/prism-src/build/bin/llama-server(+0x269739) [0x5dcfb465e739]
/opt/llama/prism-src/build/bin/llama-server(+0x21c159) [0x5dcfb4611159]
/opt/llama/prism-src/build/bin/llama-server(+0x27aabe) [0x5dcfb466fabe]
/opt/llama/prism-src/build/bin/llama-server(+0x27ce55) [0x5dcfb4671e55]
/opt/llama/prism-src/build/bin/llama-server(+0x21b316) [0x5dcfb4610316]
/opt/llama/prism-src/build/bin/llama-server(+0x1d1829) [0x5dcfb45c6829]
/opt/llama/prism-src/build/bin/llama-server(+0x1d37d7) [0x5dcfb45c87d7]
/usr/lib/x86_64-linux-gnu/libc.so.6(+0x2a601) [0x7fe26be2a601]
/usr/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x88) [0x7fe26be2a718]
/opt/llama/prism-src/build/bin/llama-server(+0x1c94d5) [0x5dcfb45be4d5]
Activity
professorpalmer commentedon Oct 10, 2026
A pointer for the bisect, from the details in the report: b10709 is good, b10770 crashes, and
--ctx-checkpoints 0avoids the crash.In
prism-b10709-9a9394a..prism-b10770-6684606, one commit touches context checkpoints in the server:bf197c43dserver : reuse the buffers of evicted prompt checkpoints (server : reuse the buffers of evicted prompt checkpoints #312)The others in that range that touch the server or speculative code are drafter changes (#334, #304), and this report runs without a drafter. So #312 is the first candidate: a reused checkpoint buffer that is smaller than the state written into it would fit an illegal access right after a long prompt, which is when checkpoints are created and evicted.
For comparison: our fork (bonsai-ada-surgery, base before b10709) runs with up to 32 checkpoints per slot, plus checkpoints inside long messages, on 8 GB and 12 GB cards at 64k-262k. We have not seen this crash there. A revert of
bf197c43don b10770 would confirm or clear it.professorpalmer commentedon Oct 10, 2026
Reproducing on an RTX 4070 (sm_89, 12 GB) with your command:
prism-b10770-6684606as is, then the same build withbf197c43d(#312) reverted. Results here within a few hours.professorpalmer commentedon Oct 10, 2026
First result from the RTX 4070 (sm_89, 12 GB, CUDA 13, Windows): not reproduced with your command (
-c 65536 -np 1 -fa on -ctk q4_0 -ctv q4_0 --jinja --reasoning-budget 2048 ..., default-b/-ub, no drafter), a needle prompt with the code word at the start,max_tokens3000:prism-b10770-6684606bf197c43d(#312) revertedYour 16k observation does reproduce here, though: with
--reasoning-budget 2048all 3000 tokens went to thinking andcontentwas empty, on both builds and both prompts. So the budget is not applied on b10770 with this command. That is a separate problem from the crash.Differences from your machine: 12 GB vs 8 GB of VRAM, sm_89 vs sm_86, CUDA 13 vs 12.4. Next I hold ~4 GB of VRAM with a second process, so the server has about what an 8 GB card has, and run the same pair again. A
compute-sanitizer --tool memcheckrun on your machine would name the faulting kernel directly (it is slow, so the 30k prompt is enough).Powerful-Plantain commentedon Oct 10, 2026
Thanks for the pointer. Tested it: reverting
bf197c43d(#312) does not fix the crash.git revert --no-commit bf197c43donprism-b10770-6684606(applies cleanly, onlytools/server/server-context.cpp), clean rebuild, same flags,CUDA_LAUNCH_BLOCKING=1:illegal memory access, same location (launch_fattn,fattn-common.cuh:1113)content,finish_reason: lengthSo #312 is cleared.
--ctx-checkpoints 0still avoided the crash in my one run, so whatever faults seems to interact with checkpoint creation/restore rather than buffer reuse — on a hybrid model that would include the recurrent (GDN) state. Remaining candidates in range that touch this path on sm_86: #221, #318, #189, #216, #214.Happy to revert any of those individually, or run a
git bisectacrossprism-b10709-9a9394a..prism-b10770-6684606(~6 steps; each build takes ~18 min on this machine). Just say which you'd prefer.professorpalmer commentedon Oct 10, 2026
Second round on the RTX 4070, with 4 GiB of VRAM held by a second process (7,755 MiB free for the server, about what your 8 GB card has), and prompts sized to yours:
prism-b10770-6684606prism-b10770-6684606So on sm_89 / CUDA 13 / Windows it does not reproduce, with or without VRAM pressure, and with or without #312. What is left that only your machine has: sm_86 kernels, CUDA 12.4, Linux, a laptop GPU with the display possibly on it. Two runs on your side would locate it:
compute-sanitizer --tool memcheck ./llama-server ...with the 30k prompt. It reports the faulting kernel and the address.--ctx-checkpoints 0crossed with-ub 256. Your table already shows that checkpoints 0 avoids the crash;-ub 256changes how the last part of the prompt is split, which tells whether the crash depends on the batch shape at the end of the prompt.Scripts:
bench/prism346_repro.shandtools/vram-ballast/in professorpalmer/bonsai-ada-surgery.Powerful-Plantain commentedon Oct 10, 2026
Thanks for testing on the 4070. Results from my machine (RTX 3070 Laptop, sm_86, CUDA 12.4, Linux):
Environment: no display on the dGPU (
nvidia-smi -q:Display Active: Disabled); the only process on the GPU is llama-server;compute-sanitizeris available.Matrix on
prism-b10770-6684606, 30,184-token prompt,CUDA_LAUNCH_BLOCKING=1:-ub 256crashes the same way.--ctx-checkpoints 0, 4/4 runs pass (30K and 45K); with default checkpoints, every run ≥30K crashes (6/6, including the two with server : reuse the buffers of evicted prompt checkpoints #312 reverted).-c 32768.Running
compute-sanitizer --tool memcheckon the 30K prompt overnight (at-c 32768for VRAM headroom); will post the faulting kernel and address.professorpalmer commentedon Oct 10, 2026
Thanks, that matrix narrows it a lot: checkpoints on/off is the switch, and #312 is cleared (it crashes with #312 reverted).
Why checkpoints matter here: with checkpoints on, the server processes the last 4 tokens of the prompt (and the last 4 + n_ubatch) as separate small batches, so it can save a checkpoint just before the end (
checkpoint_offsets[] = {4 + n_ubatch, 4}inserver-context.cpp). With--ctx-checkpoints 0the last batch is a normal one. So the first new thing after "progress = 1.00" is a 4-query attention op over ~30k q4_0 cells, plus the recurrent-state copy for the checkpoint.Two more variants on the RTX 4070, same command, 30,176- and 44,954-token prompts, 4 GiB of VRAM held, same prompt split as yours (… 29,660 → 30,172, then the 4-token batch):
So neither the sm_86 code nor the 40-SM work split reproduces it here. What remains is specific to your machine: CUDA 12.4 / driver 595 on Linux. The sanitizer run will say which kernel it is. If it is not conclusive, a bisect on your side is short:
prism-b10709..prism-b10770is 52 first-parent commits (about 6 builds). The ones that touch this path, to try first as single reverts on b10770:0d1825501cuda: avoid short-query MMA FA crash with quantized V (cuda: avoid short-query MMA FA crash with quantized V #189)5244ceadein-place q4_0/q8_0 K/V flash attention (cuda: Bonsai 2 27B at the full 262k window with the MTP head on 12 GB Ada: #218 + #215 hybrid PTQ1_0 dispatch, in-place q4_0/q8_0 K/V flash attention (integration checkpoint) #221)8e18ce3becuda: keep the GDN state gather when its ids memory is reused (cuda: keep the GDN state gather when its ids memory is reused #318)56f21fb10kv-cache: limit seq_rm to the used cell range (kv-cache : limit seq_rm to the used cell range #311)Separate finding, also on b10770 here:
--reasoning-budget 2048is not applied with this command (all 3000 tokens are thinking,contentempty), which matches your 16k observation.Powerful-Plantain commentedon Oct 11, 2026
memcheck found it.
compute-sanitizer --tool memcheckonprism-b10770-6684606, 30,184-token prompt,-c 32768, default checkpoints:So the fault is the q4_0 → f16 conversion of K/V inside
launch_fattnfor the MMA f16 kernel (D=256, 8×8): the f16 destination is ~95 KB smaller than what's written into it. That's the earlier kernel theCUDA_LAUNCH_BLOCKINGtrace couldn't name.My guess (not verified): with checkpoints on, the end of the prompt is evaluated in a batch shape that routes this op to the convert-to-f16 path instead of #221's in-place quantized read, and the scratch reserved for that conversion (
ggml_cuda_flash_attn_ext_get_alloc_sizeafter #221) is sized for less than the ~30K-cell K/V view. With--ctx-checkpoints 0the path isn't hit. #189's short-query routing may also be involved.Full memcheck log available if useful. Happy to test a fix branch on the same setup.
professorpalmer commentedon Oct 11, 2026
Thanks, the memcheck trace pinned it. Fix in #350.
With q4_0/q8_0 K/V and 3-4 queries, the short-query MMA route from #189 converts K and V to f16 in the op's extra buffer. But
get_alloc_size(from #221) reserved no f16 buffer when the in-place quantized kernel exists. So the f16 K was written past the allocation: yourdequantize_block_q4_0fromlaunch_fattn,mma_f16_case<256, 256, 8, 8, F16>. Checkpoints evaluate the last 4 prompt tokens as their own batch, and that is why--ctx-checkpoints 0avoids it.On my 4070 the 3-query D=256 q4_0 case trips a new assert without the fix and passes with it. The whole
FLASH_ATTN_EXTsuite passes 4007/4007. Could you run your crashing command on branchfix-346-short-query-scratch(PR #350)?Powerful-Plantain commentedon Oct 12, 2026
Tested on the machine from #346 (RTX 3070 Laptop, sm_86, CUDA 12.4, Linux),
e48c865d1on top ofprism-b10772-e8fd209, same flags, default context checkpoints,CUDA_LAUNCH_BLOCKING=1. Fixed.stopstoplengthstoptool_calls)No illegal access, no assert, no FA fallback warning in any log; 7083 MiB loaded. Against b10709 at 45K: prefill 271 → 437 t/s, decode 15.6 → 21.1 tok/s.
The 16K runaway answer is gone too. I can't tell whether that was this fix or #340/#347 in the base.
Thanks for the quick turnaround. Happy to run
compute-sanitizeron this build if you want a 0-error confirmation.Now running this build in production; a live 35K-context Hermes session is clean.
professorpalmer commentedon Oct 13, 2026
Thanks for the full test on the 3070. All five cases pass, with no assert and no fallback warning. That closes the crash for #350.
compute-sanitizer --tool memcheckon this build with the ~30K prompt, if it is easy for you. A 0-error result is a good record on cuda: reserve the f16 K/V scratch for the short-query MMA route (#346) #350.Powerful-Plantain commentedon Oct 14, 2026
memcheck on the same 3070 (sm_86, CUDA 12.4, Linux): 0 errors.
Binary: the installed production build, b10773 =
e48c865d1onprism-b10772-e8fd209(sha256 identical to the build that passed the earlier tests).compute-sanitizer --tool memcheck, 30,184-token prompt, default context checkpoints,-c 32768, q4_0 K/V, FA on — the same setup that reportedInvalid __global__ writeindequantize_block_q4_0<__half>on b10770.ERROR SUMMARY: 0 errorsstop(The log ends with a CUDA error after "Received second interrupt" — my test script sent a second stop signal before the slow sanitized shutdown finished. That's after the request completed and isn't related to the fix.)
That's consistent with your explanation of the 16K runaway as the same overflow landing in a live allocation. I've been running this build in production since the 12th, including Hermes sessions past 35K context — no issues. Thanks again for the quick fix.
professorpalmer commentedon Oct 14, 2026
Thank you.
0 errorson the same setup that showed the invalid write (95,747 B past the f16 buffer) on b10770 is the clear record we wanted for #350.#350 now has a merge conflict with the current base. I am rebasing it today and will post the new commit there. The fix itself does not change.
professorpalmer commentedon Oct 14, 2026
Update: the fix for this crash is in the PrismML base now, through #355 (it keeps the quantized K/V type in the short-query route, so the conversion that wrote past the buffer does not happen). I closed #350 as superseded. On the current base, all 4335
FLASH_ATTN_EXTop tests pass on an RTX 4070, including the 3-4 query cases with q4_0 / q8_0. A build from the currentprismbranch includes the fix, so you no longer need the #350 patch.