Eval bug: DeepSeek-V4 emits only repeated `<` whenever a prompt spans more than one forward pass — CUDA flash attention (clean on CPU, clean

当 DeepSeek-V4 模型的 prompt 需要多个 forward pass(即一个 batch/ubatch 装不下)时,在 CUDA + flash attention 开启的情况下,模型只会输出重复的 `<` 字符。优先排查是否启用了 CUDA flash attention,并尝试用

快速结论:当 DeepSeek-V4 模型的 prompt 需要多个 forward pass(即一个 batch/ubatch 装不下)时,在 CUDA + flash attention 开启的情况下,模型只会输出重复的 `<` 字符。优先排查是否启用了 CUDA flash attention,并尝试用 `–flash-attn off` 或调整 `-ub` 让 prompt 在一次 forward pass 内完成。

适用环境:llama.cpp(version 10233/0ab9d6fed 及 b10217/ddd4ec142、master),Ubuntu 26.04 LTS,NVIDIA GeForce RTX 5090(sm_120a),驱动 610.43.02,CUDA UMD 13.3,nvcc 13.3.73,模型 unsloth/DeepSeek-V4-Flash-0731-GGUF(UD-IQ1_S、UD-IQ3_XXS、UD-Q2_K_XL,arch deepseek4)。另有一台 RTX PRO 6000 Max-Q(Blackwell)上无法复现。

最快修复方案:暂无确认的“一步修复”方案。已验证的临时处理方法是关闭 flash attention(`–flash-attn off`),或用足够大的 `-ub`(如 `-ub 4096`)让 prompt 在一次 forward pass 内完成。两者均能输出正常结果,但会牺牲 prefill 速度(FA 开启时 391.3 t/s,关闭后降至 272.8 t/s)。

注意事项:Issue 中确认 `-b == -ub` 并不能解决问题(30255 token、8192 batch/ubatch、4 个 batch 仍 CORRUPT),因此问题与“batch 内 ubatch 拆分”无关,而是任何额外的 forward pass 都会触发。极小 `-ub`(1–96)反而正常,且最大正常 `-ub` 随 prompt 增长而缩小(1.8k token 时 ≤96,14.4k 时 ≤64)。`–flash-attn off` 不适用于超大上下文:非 FA 路径会为每个 head(64 个)物化显式 `[n_tokens × n_kv]` 分数矩阵,加载 131072 上下文时内存开销巨大。

问题场景

在 llama.cpp 的 llama-server 中加载 DeepSeek-V4-Flash GGUF 模型(deepseek4 架构),使用 CUDA 后端并开启 flash attention(-fa on)。当 prompt 无法在单个 batch 和单个 micro-batch 中全部处理完毕(即需要多个 forward pass)时,prefill 阶段报告正常吞吐,但生成结果只有重复的 < 字符,无任何报错或警告。

报错原文

Actual: '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<'
Expected: normal text. Re-run with -ub 4096 (single pass) or -fa off and it is correct.

原因分析

可能原因:CUDA flash attention 内核在处理 DeepSeek-V4 的 head 几何(DKQ=576、DV=512)且 KV cache 中已有先前 token(即 n_kv > n_tokens)时存在缺陷,该缺陷仅在 prompt 跨多个 forward pass 时暴露。Issue 作者对比了 #26434(OpenCL 通用 flash-attention tile 内核中的写后读竞争条件)后认为,CUDA MMA FA 内核可能存在类似的未加 barrier 的 shared-tile 重载问题。

已排除的可能原因:

  • KV cache 重建问题(#26460)——仅影响 -fa auto,本报告使用显式 -fa on
  • FA head size 192/128 与 GQA ratio 非 8 的倍数(#26404)——DeepSeek-V4 的 gqa_ratio=64。
  • 输入数量超限(#26496)——作者已将 GGML_SCHED_MAX_SPLIT_INPUTS 从 30 提高到 128 并验证问题依旧存在。

值得注意的是,即使 -ngl 0(不卸载任何 layer 到 GPU),只要 op-offload 仍在 GPU 上执行(VRAM 占用 1800 MiB),问题依旧复现。只有完全从进程中移除 CUDA(CUDA_VISIBLE_DEVICES="" + --no-op-offload)才能得到干净输出。因此 -ngl 0 单独使用不能视为 CPU-only 测试。

环境排查

  • 确认 llama.cpp 版本(10233、b10217 或 master)
  • 确认 CUDA 版本(13.3 可复现;12.8 在另一台 Blackwell 机器上无法复现,但同机换 12.8 未验证)
  • 确认显卡为 Blackwell 架构(RTX 5090/RTX PRO 6000 Max-Q),驱动版本(610.43.02)
  • 确认模型为 deepseek4 架构(unsloth/DeepSeek-V4-Flash-0731-GGUF,UD-IQ1_S/UD-IQ3_XXS/UD-Q2_K_XL)
  • 确认 -b / -ub 的设置:-b == -ub 不能规避问题,需 -ub 足够大让 prompt 一次通过
  • 确认 KV cache 类型:Issue 使用 f16 KV(无 --cache-type-k/v),排除 #25382

解决步骤

  1. 优先尝试临时方案 A:关闭 flash attention,使用 --flash-attn off(代价是 prefill 速度下降约 30%,且大上下文内存开销巨大)。
  2. 优先尝试临时方案 B:增大 -ub 使 prompt 在单个 forward pass 内处理完毕。示例:1811 token 用 -ub 4096;14379 token 用 -ub 16384。注意 -ub 不能无限增大,且需确保 -b-ub
  3. 如上述方案不可行,可尝试将 -ub 设为极小值(1–96),Issue 中该范围表现正常,但最大可用 -ub 随 prompt 长度缩小,需根据实际 prompt 长度试验。
  4. 如果必须使用 CUDA + FA,请关注 llama.cpp 仓库后续修复,特别是针对 CUDA MMA FA 内核在 n_kv > n_tokens 路径下的 barrier/shared-tile 修复。

验证方法

用确定性 prompt(如 Issue 中提供的 Python 生成的 90 行文本,约 1.8k token)调用 /completion 接口,设置 n_predict=40temperature=0.0cache_prompt=False。比较不同配置下的输出:-fa on -ub 512 应输出重复 <(复现问题),改为 -fa off-ub 4096 后输出应为正常文本。同时确认 prefill 速度是否与预期一致(FA on 约 391 t/s,FA off 约 273 t/s)。

参考来源

ggml-org/llama.cpp #26509

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 20731

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注