Repository navigation
cuda: avoid short-query MMA FA crash with quantized V - #189
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
The new branch selects an unsupported 64-column specialization on Turing GPUs.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adjusts CUDA FlashAttention dispatch to avoid the failing 32-column MMA path for short queries with quantized V caches.
Changes:
- Detects quantized V caches with query lengths 3-4.
- Routes matching workloads to the 64-column specialization.
File summaries
| File | Description |
|---|---|
ggml/src/ggml-cuda/fattn.cu |
Adds the short-query MMA dispatch fallback. |
Review details
- Files reviewed: 1/1 changed files
- Comments generated: 1
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| const ggml_tensor * Q = dst->src[0]; | ||
| const ggml_tensor * V = dst->src[2]; | ||
|
|
||
| if (turing_mma_available(cc) && ggml_is_quantized(V->type) && Q->ne[1] > 2 && Q->ne[1] <= 4) { |
bri-prism
left a comment
There was a problem hiding this comment.
Agent review: posted by the maintainer's coding agent at their request.
No findings in this source pass. The fallback is narrowly scoped to quantized V and query lengths 3-4, using the existing larger MMA specialization.
CUDA compilation and device execution were not performed here. Before merging, please retain boundary coverage at query lengths 2, 3, 4 and 5 with quantized and unquantized V, including the applicable grouped-query specializations. The reported model evaluation is useful evidence but was not rerun in this review.
Reviewed commit: 19836568c4f1b504d8ee579b7ab7fcf4edbd8f78.
|
Validation was performed on build 1983656 using an RTX 4080 (SM89) with FlashAttention enabled. Test configuration: Model: Ternary-Bonsai-2-27B-PTQ1_0.gguf (Qwen3.5 27B) All 12 configurations completed successfully with no CUDA errors. This validates the quantized-V fallback path for Q = 3–4, as well as the boundary cases Q = 2 and Q = 5. The Turing-specific issue remains unresolved, since testing was performed only on Ada / RTX 4080 hardware. |
|
Agent benchmark follow-up, posted at the maintainer's request. Pinned head
Selected CPU-reference backend checks passed on the compared arms. The short-query quantized-V attention checks and small-batch timings were included. No crash was observed in the selected completed cases; this does not exhaust all attention shapes. The percentages describe these paired runs; small changes should not be interpreted as established improvements. No long-context, multi-slot serving, or end-to-end logit-parity claim is made. PQ2 control measurements (paired pp512 / tg128 changes):
|
|
I tried this on an RTX 4070 (Ada, cc 8.9) with Ternary-Bonsai-2-27B and found two problems on the MTP decode path. I could not reproduce the original crash, so this is only about the side effects. Setup: the patch applied cleanly on current Speed. Ternary-Bonsai-2-27B PTQ1_0 + MTP head,
The MTP verify step has 3 queries, so with q4_0 V it takes the new test-backend-ops. What I could not check. The crash this PR fixes (K f16, V quantized, Q 3-4) needs mixed K/V types. With the default build those fall back to the CPU (see #267), so I could not trigger it. With matching types (q8_0/q8_0, q4_0/q4_0), The measurements and scripts were run with Claude Code; I can post the exact commands if useful. |
|
@bri-prism @Wyzix33 after this merged, I built three commits (CUDA arch 89, Release, same flags):
So it comes in with this commit, and #317 does not fix it. The cases before it in the list (same shape, The diff itself is six lines in In the #317 thread the plan was to land #317 and close #189 in its favour, because #189 also hit an illegal memory access in testing. Since #189 was merged anyway, it may need a revert or a fix. The checks were run with Claude Code (AI assistance). |
|
@bri-prism @Wyzix33 follow-up: the cause is in the shortcut added here, and I opened #337 with a one line fix. The shortcut calls the 64 column MMA kernel without The effect is not only the test abort: on Ternary-Bonsai-2-27B with MTP The fix and the checks were made with Claude Code (AI assistance); details are in #337. |
The shortcut added in PrismML-Eng#189 calls the 64 column MMA kernel without type_KV, so it always builds the f16 variant. With head size 128 or 256 and q4_0/q8_0 K/V the in-place quantized kernel is used and no f16 scratch is reserved after dst. For 3 or 4 queries the shortcut then converted K and V into memory behind the reserved range (invalid write found with compute-sanitizer in test-backend-ops FLASH_ATTN_EXT, hsk=256 nq=3 q4_0, GQA 6). On the MTP decode path this also changes the output and lowers the draft acceptance. The fix adds type_KV == GGML_TYPE_F16 to the condition. AI assistance: this fix was written and checked with Claude Code (AI). It was found with compute-sanitizer, built and tested on an RTX 4070 (test-backend-ops -o FLASH_ATTN_EXT 4007/4007; sanitizer 0 errors on the PrismML-Eng#189 commit with the fix) and measured with 8 interleaved A/B pairs of MTP decode. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Li7aNoBEvKTV1NBubgCCKg
…ery fallback PrismML-Eng#189 sends 3..4-token queries with a quantized V to the MMA case with ncols1 = 64/ncols2. It was written before PrismML-Eng#221 added the MMA variants that read q4_0/q8_0 K/V in place (template parameter type_KV), and its call does not pass type_KV. So with -ctk/-ctv q4_0/q8_0 these queries run the f16 variant instead of the in-place one, and the results are wrong. Every MTP verify batch with --spec-draft-n-max 2 is such a query. Apply the fallback only when type_KV is F16. The in-place variants take the regular path again (as before PrismML-Eng#189); K/V that are converted to f16 keep the PrismML-Eng#189 behaviour. Test: RTX 5090 (sm_120), CUDA 13.4, llama-perplexity with prism-ml/Ternary-Bonsai-2-27B-PQ2_0, -c 512 -b 512 --chunks 6 -fa on -ctk q8_0 -ctv q8_0, text: GPL-3.0 license. -ub 512 4 3 PrismML-Eng#189 as is 5.1364 14.96, then nan nan this fix 5.1364 5.1365 5.1363 With an MTP head (--spec-type draft-mtp --spec-draft-n-max 2, q8_0 K/V) the generated text was loops and garbage before (draft acceptance ~0.2) and is clean after (155-201 t/s, acceptance 0.30-0.54).
|
For reference: the same one line change was found independently by Leeleit on an RTX 5090 (sm_120, CUDA 13.4): Leeleit@42000f6 Their report, with Ternary-Bonsai-2-27B-PQ2_0 and q8_0 K/V ( That adds a second GPU generation and a quality metric to my RTX 4070 numbers (MTP decode 94.14 -> 111.16 tok/s, acceptance 54.1 -> 71.6 %). I did not reproduce their numbers myself. |
Overview
Fix a CUDA illegal memory access in short-query MMA FlashAttention when using a quantized V cache.
For MMA-capable GPUs, Q lengths 3–4 with quantized V are now routed to the existing ncols=64 specialization instead of the crashing ncols=32 path.
Reproducer
Tested on:
RTX 4080 / SM89
CUDA 12.4
Windows / MSVC
Bonsai 2 27B PTQ1_0
FlashAttention enabled
Failing shape:
Q length: 4
K: f16
V: q8_0
24 Q heads / 4 KV heads
KV length: 1280
The ncols=32 MMA specialization produced a CUDA illegal memory access in launch_fattn. The same cache worked with the ncols=64 specialization.
Validation
After the change:
-fa on -ctk q8_0 -ctv q5_1
GSM8K: 1319/1319 completed
no CUDA crashes
no repeated-slash corruption
clean-build smoke test: 50/50 completed
This is a narrow dispatch fallback, not a low-level fix for the ncols=32 kernel.
Requirements