Eval bug: on HIP, a sequence whose prompt shares a llama_decode() batch with another sequence’s decode row gets corrupted logits, and every

在 HIP(ROCm)后端下,当一个新序列的 prompt 行与另一个正在生成序列的 decode 行被放进同一个 llama_decode() batch 时,加入方序列(seq 1)的首个采样 token 就会出错,并退化成 3–7 个 token 的循环,但所有调用仍返回成功。优先确认是否在使

快速结论:在 HIP(ROCm)后端下,当一个新序列的 prompt 行与另一个正在生成序列的 decode 行被放进同一个 llama_decode() batch 时,加入方序列(seq 1)的首个采样 token 就会出错,并退化成 3–7 个 token 的循环,但所有调用仍返回成功。优先确认是否在使用 HIP 后端、以及是否为 llama-server -np N 这类“新 slot 启动时恰好有其他 slot 在生成”的 batch 形状。

适用环境:llama.cpp 0.3.0-dev(build 10798, commit c390d0abb;首次在 b10760 测到,b10798 与 b10819 release tarball 复现);Linux,Ubuntu 24.04.4 LTS 容器(glibc 2.39, g++ 13.3.0),宿主 Fedora Linux 44,kernel 7.1.9-200.fc44.x86_64;HIP 后端;AMD Radeon 8060S Graphics(gfx1151, AMD Ryzen AI MAX+ 395, 57344 MiB, x64, Wave Size: 32, VMM: no);ROCm 7.2.4 与 ROCm 10.0(amdrocm-core10.0-gfx1151 10.0.0-4, HIP runtime 7.15.26333)均复现;模型 Qwen3-1.7B-Q4_K_M,KV cache q8_0f16

最快修复方案:Issue 正文与讨论中指向的修复是升级到包含 PR #28604 的构建版本;该 PR 被标记为应修复此问题,但 Issue 中未给出升级后自行验证的复现数据,因此可优先尝试,不作为已确认的一步修复方案。

注意事项:该问题只在 HIP 后端复现,同一 GPU、同一宿主、同一构建下 Vulkan(RADV GFX1151, Mesa 25.2.8)与 CPU 对照均未出现序列损坏;因此临时规避可考虑改用 Vulkan 或 CPU 后端,但这只是 Issue 中的对照结果,并非官方推荐或长期方案。PR #28604 的修复效果需以你自己环境实测为准。

问题场景

在 HIP(ROCm)后端运行 llama.cpp 时,只要一个 batch 里同时包含“某个序列的 prompt 行”和“另一个序列的 decode 行”,加入方序列就会拿到被污染的 logits。最典型的触发方式是 llama-server -np N:一个 slot 正在生成,另一个 slot 刚开始启动。Issue 中给出的确定性复现命令为:

./repro Qwen3-1.7B-Q4_K_M.gguf -ngl 99 -n 512 -stagger 40

其中 -stagger K 表示把序列 1 的 prompt 行与序列 0 的第 K 个 decode 行放进同一个 batch。变体测试(HIP)包括 -stagger 1-stagger 5-stagger 40-stagger 40 -f16-stagger 40 -f16 -nofa,全部 corrupt。

报错原文

Eval bug: on HIP, a sequence whose prompt shares a llama_decode() batch with another sequence's decode row gets corrupted logits, and every call reports success

Issue 中描述的关键现象是三处调用都不报错:llama_decode() 返回 0llama_get_logits_ith() 为每个请求的行都返回指针,采样照常进行——但用的是垃圾 logits。复现程序用贪心 argmax 直接从 llama_get_logits_ith() 取结果,不涉及 sampler。

原因分析

可能原因:HIP 后端在处理“prompt 行与 decode 行混合在同一个 llama_decode() batch”的 batch 形状时,logits 计算或相关中间结果被错误复用/覆盖,导致加入方序列的输出行被污染。Issue 中的三方对照支持这一判断:

  • CPU 后端下,生成中的序列 seq 0first_div 为 512/512(完全不受加入影响);
  • Vulkan 后端下为 298,属于较晚的数值漂移;
  • HIP 后端下为 40,且 -stagger 15 分别为 1 和 5——即在 prompt 加入的那一步立刻偏离。

语义上本应满足:一个序列加入 batch 不应影响其他序列。CPU 全程 512 个 token 与单独运行逐字节一致,说明 HIP 违反了这一语义。此外,两个序列的 prompt 在同一个 batch 中、之后同步解码的情形是干净的,出问题的只是“生成中途加入”这种 batch 形状。

环境排查

  • 确认后端是否为 HIP(ROCm),以及 llama-cli --version / 构建 commit 是否落在 b10760–b10819 这一区间。
  • 确认 GPU 是否为 AMD gfx1151(如 Radeon 8060S / Ryzen AI MAX+ 395),并注意 Issue 中记录的 Wave Size: 32VMM: no
  • 确认 ROCm 版本:Issue 在 ROCm 7.2.4 与 ROCm 10.0(HIP runtime 7.15.26333)下均复现。
  • 确认是否使用 llama-server -np N 或任何会让新序列的 prompt 与在途 decode 行同批提交的调度方式。
  • 确认 KV cache 类型(q8_0f16)与 -f16-nofa 等参数组合;Issue 中这些组合在 HIP 下都 corrupt。
  • 可用 Vulkan(RADV GFX1151, Mesa 25.2.8)或 CPU 跑同一命令作为对照,确认是否是 HIP 专有行为。

解决步骤

  1. 先记录当前版本与构建 commit,确认处于受影响的 b10760–b10819 区间。
  2. 在 HIP 后端上用 Issue 的复现命令(-ngl 99 -n 512 -stagger 40)跑一次,记录 seq 1first_divmaxrundistinct。Issue 中 HIP 的 10 次运行全部出现 seq 1 corrupted,first_div 恒为 0,maxrun 为 509 或 1,distinct 为 3 或 7;两种退化形态交替出现。
  3. 用同一命令在 Vulkan 和 CPU 后端各跑对照组,确认只有 HIP 出现 seq 1 崩溃,且 CPU 下生成中序列与单独运行逐字节一致。
  4. 升级到包含 PR #28604 的构建版本(可优先尝试)。
  5. 升级后重复第 2、3 步,重点观察 seq 0first_div 是否恢复到与 CPU 一致的 512/512 量级,以及 seq 1 是否不再从第 0 个 token 就偏离。
  6. 若暂时无法升级,可临时改用 Vulkan 或 CPU 后端运行相同负载,作为规避手段。

验证方法

用同一复现命令在 HIP 下重复多次运行,确认:加入方序列的 first_div 不再为 0,distinct 不再跌到 3–7,maxrun 不再出现 509;同时在途序列 seq 0first_div 应回到 CPU 对照的 512/512 水平,或至少不再是“prompt 加入当步即偏离”。最直接的判定标准是:一个序列加入 batch 不应改变其他序列的输出流。此外,由于 Issue 报告所有调用都返回成功,验证不能只看返回值,必须检查实际生成 token 流。

参考来源

ggml-org/llama.cpp #28537

ggml-org/llama.cpp PR #28604

GamsGo AI

AI 工具推荐

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

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

了解 GamsGo AI

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

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 22666

发表回复

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