Repository navigation
qwen4exp: GGML_ABORT ("maskless selected-key attention was not taken by a QSA kernel") on KV-cache exhaustion under --kv-unified with concurrent slots #85
Description
Name and Version
Built from this repo at commit 8c1c282ec (2026-09-17, current master HEAD as of this report), build tag 11195. HIP/ROCm backend, on a retained-PM4 ROCm runtime build (pwilkin/rocm-systems ilintar-experiments @ 7dda3ac6cf), built 2026-09-21.
Operating systems
Linux (Fedora 43, kernel 6.18.16)
GGML backends
HIP
Hardware
Ryzen AI Max+ 395 / gfx1151 (Strix Halo), 128GB unified memory
Models
Qwen3.8-Flash-Next, UD-IQ3_XXS quant (unsloth), + a separate MTP draft-model sidecar (mtp-Qwen3.8-Flash-Next-Q8_0.gguf, unsloth, non-shared variant) via --spec-type draft-mtp.
Problem description & steps to reproduce
Running llama-server with --parallel 3 -c 262144 --kv-unified (native context, shared KV pool across 3 slots) under real concurrent agentic-coding traffic (multiple simultaneous requests, several with 50k-120k+ token contexts). Not synthetic — this is our normal production serving config for this model on this hardware.
When the shared KV pool fills (one slot's prefill reaching ~124k tokens while another slot is concurrently active/growing), decode hits the "no free space in KV cache" retry path and shrinks batch size across attempts: 2048 → 1024 → 512. At the n_batch = 512 retry, ggml_cuda_flash_attn_ext receives a tensor shape that satisfies dst->src[5] && !dst->src[3] (a selected-key op with no mask) but is not recognized by either ggml_cuda_flash_attn_ext_qsa_decode_supported or ggml_cuda_flash_attn_ext_qsa_prefill_supported, so it falls through to the GGML_ABORT guard in ggml/src/ggml-cuda/fattn.cu:778 and the process dies (SIGABRT).
This reliably brings the whole llama-server process down (confirmed via llama-swap's upstream-process-exited-unexpectedly + auto-restart, and via journalctl / container exec_died), not a single-request failure.
Reproduction command (production config)
llama-server -m Qwen3.8-Flash-Next-UD-IQ3_XXS-00001-of-00003.gguf \
-ngl 999 -fa 1 --load-mode none --parallel 3 -c 262144 -ctk q8_0 -ctv q8_0 --kv-unified \
--jinja --metrics -ub 2048 -b 2048 -ctk f16 -ctv f16 \
--spec-draft-model mtp-Qwen3.8-Flash-Next-Q8_0.gguf --spec-type draft-mtp --spec-draft-n-max 3 \
--spec-draft-p-min 0.0 --lazy-mode on-direct --checkpoint-min-step 16384 --cache-ram 4096
Note -ctk/-ctv are specified twice (q8_0 then f16) — this is intentional in our config; the launcher hardcodes q8_0 and we override to f16 via extra flags, and llama.cpp takes the last occurrence (confirmed via the startup log's own deprecation warning, which is expected/harmless here).
I don't yet have an isolated minimal repro (e.g. exact token counts / timing to force it synthetically) — this was caught live via production traffic with full logging. Happy to help build one if useful, e.g. a script that fills the KV pool across N slots near the ctx ceiling and forces the batch-shrink path.
Relevant log output
17.27.144.707 E init_batch: failed to prepare attention ubatches
17.27.144.721 W decode: failed to find a memory slot for batch of size 2048
17.27.144.757 W srv decode: failed to find free space in the KV cache, retrying with smaller batch size, off = 0, n_batch = 1024, ret = 1
17.30.359.107 E init_batch: failed to prepare attention ubatches
17.30.359.113 W decode: failed to find a memory slot for batch of size 1024
17.30.359.163 W srv decode: failed to find free space in the KV cache, retrying with smaller batch size, off = 1024, n_batch = 1024, ret = 1
17.30.365.586 E init_batch: failed to prepare attention ubatches
17.30.365.590 W decode: failed to find a memory slot for batch of size 1024
17.30.365.629 W srv decode: failed to find free space in the KV cache, retrying with smaller batch size, off = 1024, n_batch = 512, ret = 1
/opt/llama.cpp/ggml/src/ggml-cuda/fattn.cu:783: flash_attn_ext: maskless selected-key attention was not taken by a QSA kernel (node_710): q [256,512,24,1] f32 nb 24576/1024, k [256,262144,2,1] f16 nb 2/1024/512, v f16 nb 1024/512, ids [2051,512,1,1] nb 8204, src6 0 src7 0 p4 0 dst contiguous 1
/usr/local/lib64/libggml-base.so.0(+0x6874) [0x7fe54c961874]
/usr/local/lib64/libggml-base.so.0(ggml_print_backtrace+0x1e0) [0x7fe54c961ce0]
/usr/local/lib64/libggml-base.so.0(ggml_abort+0x11d) [0x7fe54c961e8d]
/usr/local/lib64/libggml-hip.so.0(_Z24ggml_cuda_flash_attn_extR25ggml_backend_cuda_contextP11ggml_tensor+0x1ee6) [0x7fe551774a06]
/usr/local/lib64/libggml-hip.so.0(+0x4d54c70) [0x7fe5517d2c70]
/usr/local/lib64/libggml-hip.so.0(+0x4d471a7) [0x7fe5517c51a7]
/usr/local/lib64/libggml-base.so.0(ggml_backend_graph_compute_async+0x14) [0x7fe54c97b0e4]
/usr/local/lib64/libggml-base.so.0(ggml_backend_sched_graph_compute_async+0x875) [0x7fe54c9810b5]
/usr/local/lib64/libllama.so.0(_ZN13llama_context13graph_computeEP11ggml_cgraphb+0xa0) [0x7fe55260b5a0]
/usr/local/lib64/libllama.so.0(_ZN13llama_context14process_ubatchERK12llama_ubatch14llm_graph_typeP22llama_memory_context_iR11ggml_status+0x1ca) [0x7fe55260f30a]
/usr/local/lib64/libllama.so.0(_ZN13llama_context6decodeERK11llama_batch+0x37b) [0x7fe55261421b]
/usr/local/lib64/libllama.so.0(llama_decode+0xe) [0x7fe552615d1e]
The q [256,512,24,1], k [256,262144,2,1], ids [2051,512,1,1] shapes are from the moment of the abort: k's second dim (262144) matches our full context ceiling, and the shrunk batch size (512) shows up in q's second dim — consistent with this being specifically the retry-at-reduced-batch-size path producing a shape the QSA dispatch checks don't cover.
System state at the time
Concurrent host memory pressure was also present (main system RAM ~120Gi/123Gi used, swap 7.9Gi/8.0Gi) though this looks like a kernel-dispatch/shape-coverage bug rather than an OOM — the abort is a deliberate GGML_ABORT guard, not a memory allocation failure, and system memory pressure was likely just a side effect of the KV pool growing this large rather than the direct trigger.
First Bad Commit
Unknown — this is the first time we've hit it; our build (8c1c282ec) is current master. Possibly present since the QSA dispatch kernels were introduced; haven't bisected.
Activity
joshvoigts commentedon Sep 30, 2026
I'm seeing the same error and crash. Seems to occur near the end (or possibly at the end of the maximum context).
Build: strix-llama.cpp=12643af64 (master), rocm_systems=7dda3ac6cf (ilintar-experiments)
gfx1151 / HIP, -c 262144 --kv-unified, n_slots=1, MTP draft (mtp-Qwen3.8-Flash-Next-shared-Q8_0.gguf), not --parallel.
klucsik commentedon Sep 30, 2026
Second data point + the exact trigger band (and a proposed gate fix)
Production, gfx1151 / HIP, build
12643af64(= master at the time),-c 262144 --kv-unified -np 2 --flash-attn on --cache-type-k f16 --cache-type-v f16 --fit off, MTP+ngram-mod speculation:The child instance exited with status 1 and the multi-model supervisor respawned it — which is why the container
restartCountstays 0 and the Pod never looks unhealthy. Slot occupancy at the abort: 153,781 + 108,067 = 261,848 of 262,144 cells used, i.e. two concurrent slots filling the unified cache from opposite ends.The gate and the kernels disagree
qwen4exp_use_block_selection()(src/models/qwen4exp.cpp:812) admits the maskless route up ton_kv <= 16777216. The kernels that must execute the resulting op are far stricter, and they disagree with each other by 4 cells:qsa_prefillk->ne[1] <= 262140,%4 == 0uint16with0xFFFFreserved as the empty sentinel →65535 * ratio(4)q->ne[1] >= 128qsa_decodek->ne[1] <= 262144q->ne[1] <= 512llama_kv_cache::get_n_kv()pads the used extent to 256 (n_pad_cur = max(n_pad, 256)), so a 262144-cell cache exposes exactly one depth past the prefill bound: every used count in261889..262144reportsn_kv = 262144. The rung below it is 261888, which is inside the bound.fattn.cutries decode, then prefill. So the fatal combination is narrow and fully determined:Every prefill clause that the abort string exposes passes on our node (853 ≥ 128,
ids->ne[0]=2051 ≤ 2560,ids->nb[1]=8204so%4==0,k->nb[1]=1024/k->nb[2]=512so%16==0, f16 K/V, head 256, 24 = 12×2 GQA, dst contiguous,src6/src7null,p4 0, bias/softcap 0) — the only two clauses not printed are theq->data/k->data/ids->dataalignment tests, which are satisfied in practice because these are graph-allocated buffers. So the op is 4 keys of depth away from being servable, and decode can't take it only because of the 512-query cap. Note262144 % 4 == 0, so this isn't an artifact of the alignment clause: the two caps genuinely differ, and the llama-side gate is checked against neither.This also explains #85's own node — and predicts it is partially fixed
#85 and @joshvoigts's report both show
q=512at depth 262144. On those builds (8c1c282ec, before9bc06f5f7"qsa : take 1..512 queries in the per-query decode kernel") the decode cap was 8, so a 512-token ubatch fell through both gates for the same structural reason. After9bc06f5f7, decode acceptsq <= 512at 262144 — so I'd expect your exact node to be served now; worth re-testing on current master. The band that survives on master isq > 512, which is what we hit.Proposed fix: gate on the intersection of the kernel bounds
Cost is one padded rung: used cells 261889..262144 served by a >512-token maskless ubatch fall back to the masked route (261888 is a multiple of 4, so prefill alignment is respected; decode at
q <= 512and depth 262144 stays on the QSA path). Becauseget_n_kv()quantises to 256, this is a single rung, not a sliding window.Hardening alternatives, if you'd rather not tighten the model-side gate:
%4requirement, orn_kv == 262144⇒ onlyq <= 512may be maskless).Relation to #115 and #110
selected_key_attnbackend-capability flag into this exact expression, but its description states it "does not change ROCm, so it does not fix qwen4exp: GGML_ABORT ("maskless selected-key attention was not taken by a QSA kernel") on KV-cache exhaustion under --kv-unified with concurrent slots #85". On HIP the flag is always true, so a 262144-depth / >512-query ubatch still aborts. Since it already rewrites this line, it'd be a natural place to also capn_kvat the selected-key depth bound.Rebuild-free workaround
-c 261888(256-aligned, soGGML_PAD(n_ctx, 256)leaves it;n_ctx_seq == 261888 <= 262140under--kv-unified). The cache can never report the fatal rung, for 0.1 % of context. Not yet applied on our side (we have no write access to the ConfigMap), so this is a proposed mitigation rather than a verified one.Repro recipe
Two concurrent sessions on
-c 262144 --kv-unified -np 2 --flash-attn on --cache-type-k f16 --cache-type-v f16 --fit off,n_swa == 0. Drive combined used cells past 261888 (we were at 261,848), then send a >512-token incremental prompt to the slot with the shorter prefix so it doesn't split into <=512 chunks.--ubatch-size 1024makes it deterministic. Full 787 s log available.Confirmed present in
12643af64;fattn.cu,qsa-decode.cuandqsa-prefill.cuare byte-identical in current8b7217718, and no branch in the repo relaxes the 262140 bound (0636c9aeeintroduced it).llama : cap maskless block selection at the qsa_prefill depth bound (…
llama : cap maskless block selection at the qsa_prefill depth bound (…
cuda : widen QSA selected-key block ids to uint32 and lift the depth …
cuda : widen QSA selected-key block ids to uint32 and lift the depth …
cuda : widen QSA selected-key block ids to uint32 and lift the depth …