
Eval bug: Gemma4 E4B MTP drafter crashes at slot init with fatal error in fattn.cu:110
快速结论: 该报错在使用 Gemma4 E4B 模型配合 MTP (Multi-Token Prediction) draft 模型进行推测解码(speculative decoding)时触发,发生在 slot 初始化阶段的 warmup decode 过程中。优先尝试关闭 flash attention(-fa off)作为临时工作区,或应用 fattn.cu 中 case 512/576 分支的 fallback 修复。
问题场景
用户在 llama-server 上加载以下模型时触发:
- 主模型:
gemma-4-E4B-it-qat-UD-Q4_K_XL.gguf(来自 Unsloth) - Draft 模型:
mtp-gemma-4-E4B-it.gguf - 启动参数包含
--spec-type draft-mtp --spec-draft-n-max 1
硬件环境为双 RTX 3090,使用 CUDA 后端。报错在加载模型时的 common_context_can_seq_rm 调用链中出现,最终落点在 ggml_cuda_flash_attn_ext。
报错原文
ggml/src/ggml-cuda/fattn.cu:110: fatal error
ggml_cuda_flash_attn_ext → ggml_cuda_graph_evaluate_and_capture
→ llama_decode → common_context_can_seq_rm → server_context_impl::load_model
原因分析
问题根本原因是 ggml_cuda_flash_attn_ext 中针对 512 和 576 宽度(ncols)的 flash attention kernel 调度存在缺陷。在 Gemma4 E4B MTP 场景下,注意力计算的 GQA(Grouped Query Attention)ratio 超出了当前 kernel 实现所支持的路径,导致调度到了 BEST_FATTN_KERNEL_NONE 分支,从而触发 fatal error。
可能原因:
- Commit #24282 引入的 E4B/E2B 支持中,对 MTP draft 特殊形状的注意力计算适配不完整。
- Rossmann 和 Triton 后端在 dispatch 到
ggml_cuda_flash_attn_ext_mma_f16时,512宽度下的 GQA 条件未正确处理。
环境排查
- llama.cpp 版本: build 9584 (e25a32e98) 及之后版本(包括 ac4cddeb0)。
- CUDA 版本: 13.3(用户之一),建议检查 CUDA 驱动版本(610.43.02 正常)。
- ROCm 版本: 仅作记录,该问题在 AMD ROCm 后端同样出现(RX 7900 XTX)。
- 模型文件: 确认下载的 .gguf 文件完整性;特别检查 draft 模型路径与参数是否匹配。
- 编译选项: 建议确认是否开启 CUDA graphs(
GGML_CUDA_GRAPHS)—— 部分用户使用了ARCH=120a-real自定义编译。但即使无 graphs 的常规 CUDA 编译也会崩溃。
解决步骤
-
临时工作区:关闭 flash attention
在llama-server启动参数中添加-fa off。这能让模型加载和服务正常运行,MTP 推测解码仍然有效。测试结果表明关闭后draft-mtp仍可正常工作,且带来约 39% 的 p50 延迟降低。 -
应用代码级修复(开发者/自编译用户):编辑
fattn.cu文件
修改ggml/src/ggml-cuda/fattn.cu中的ggml_cuda_get_best_fattn_kernel()函数,将以下 fallback 从BEST_FATTN_KERNEL_NONE改为BEST_FATTN_KERNEL_TILE:case 512:→return BEST_FATTN_KERNEL_TILE;case 576:→return BEST_FATTN_KERNEL_TILE;
-
可选:针对 GQA ratio 的精细化修复
在ggml_cuda_flash_attn_ext_mma_f16()函数中,将原本的case 512:调用替换为基于gqa_ratio的条件分支:- 计算
gqa_ratio = Q->ne[2] / K->ne[2] - 若
gqa_ratio > 4,调用...switch_ncols1<512, 512, 8>(ctx, dst) - 若
gqa_ratio > 2,调用...switch_ncols1<512, 512, 4>(ctx, dst) - 若
gqa_ratio > 1,调用...switch_ncols1<512, 512, 2>(ctx, dst) - 否则,保留原有调用
...switch_ncols2<512, 512>(ctx, dst)
- 计算
-
重新编译 CUDA 后端
执行:cmake --build build --target ggml-cuda -j8无需完整的 clean 重新编译。
注:以上代码修改方案由 Issue 评论区讨论提供,可优先尝试但尚未被官方合并,使用者应自行评估风险。
验证方法
重新运行相同的 llama-server 命令(保持 --spec-type draft-mtp 等参数)。成功后日志中应看到 speculative decoding context initialized 和 server is listening 等信息,不再出现 fattn.cu:110: fatal error。可使用任意请求测试服务是否正常响应。



