快速结论:这个报错通常出现在 Linux CUDA 环境下运行 llama.cpp 的 test-backend-ops 测试套件时,由 ADD_ADD 融合算子的 f16/f16 用例触发。它并非 CUDA kernel 本身算错,而是 fused ADD 保留 FP32 中间结果、CPU 每次 ADD 都舍入到 FP16,两者舍入顺序不同,导致误差略超 test_add_add 继承的默认 NMSE 上限 1e-7。优先检查测试容差而不是内核实现。
适用环境:Issue 已确认:llama.cpp master(约 fa67698,另在 8212c7802 复现);Linux(self-hosted gpu-cuda runner);Windows + CUDA 13.4 + RTX 5070 Ti(评论中的测量环境)。命令为 ctest -C Release --output-on-failure -L 'main|python'。
最快修复方案:暂无确认的一步修复方案。Issue 中建议并测试过的处理是给 tests/test-backend-ops.cpp 里的 test_add_add 增加与 test_bin_bcast(见 #28691)相同的 max_nmse_err() 覆盖:当 type == GGML_TYPE_F16 时返回 1e-6。该改动在 PR #28707 的 d5cb9ea 中用于解除该 PR 阻塞,Issue 作者认为它应单独合入 master。可优先尝试。
注意事项:该方案放宽的是测试容差,不是修复 kernel;它只针对 fused f16 ADD 链的融合与 CPU 分步舍入差异,不改变 CUDA 计算结果。修改前请确认失败确为 ADD_ADD(type=f16,type_addend=f16,...) 且误差量级约 1.0e-7,而非其他类型或形状的 ADD 失败。
问题场景
在 Linux 的 gpu-cuda 环境下运行 llama.cpp 的 Release 测试套件(ctest -C Release --output-on-failure -L 'main|python')时,test-backend-ops 失败。触发点是 tests/test-backend-ops.cpp 中的 test_add_add,即融合图 ggml_add(ggml_add(a, b), c) 的 f16/f16 用例,形状 ne=[64,5,4,3]。同一 job 中 f32/f32、f16/f32 以及 f16/f16 的 ne=[1025,5,4,3] 均通过,说明不是通用 ADD kernel 缺陷。
报错原文
[ADD] ERR = 0.000000102 > 0.000000100
ADD_ADD(type=f16,type_addend=f16,ne=[64,5,4,3],broadcast=0,view=0): FAIL
Failing tests:
Backend CUDA0: FAIL
98% tests passed, 1 tests failed out of 54
The following tests FAILED:
45 - test-backend-ops (Failed)
原因分析
最可能的原因是 fused ADD 与 CPU 分步 ADD 的舍入顺序不同。CUDA 融合路径会把 a+b+c 的中间结果保留为 FP32,只在最后做一次 FP16 舍入;而 CPU 路径每次 ADD 都舍入回 FP16,再做下一次加法。两种顺序在 ne=[64,5,4,3] 这类形状上会产生约 1.0e-7 量级的 NMSE 差异,恰好超过 test_add_add 未覆盖时继承的默认上限 1e-7。
该问题与 #28691 同类:#28691 已为 test_bin_bcast 中融合 FP16 ADD 链(nf > 1)把上限提高到 1e-6,但 test_add_add 没有获得同样的覆盖。评论中的测量支持这一判断:CUDA 结果与“对 f32 和做一次 f16 舍入”一致,CPU 与“每次加法后舍入”一致;GGML_CUDA_DISABLE_FUSION=1 时 NMSE 精确为 0;100,000 次运行中约 0.827% 超过 1e-7。因此这并不是近期 kernel 回归。
环境排查
- 确认 llama.cpp 版本(Issue 中为
master约fa67698,另在8212c7802复现)。 - 确认运行平台:Linux
gpu-cudarunner;评论测量环境为 Windows、CUDA 13.4、RTX 5070 Ti。 - 确认执行命令为
ctest -C Release --output-on-failure -L 'main|python'。 - 确认失败用例是否精确为
ADD_ADD(type=f16,type_addend=f16,ne=[64,5,4,3],broadcast=0,view=0),并对比 f32/f32、f16/f32 是否通过。 - 确认
test_add_add是否缺少max_nmse_err()覆盖,因默认限制仍为1e-7。
解决步骤
- 在
tests/test-backend-ops.cpp中定位test_add_add测试用例类。 - 参照
test_bin_bcast在 #28691 中的处理,为test_add_add增加max_nmse_err()覆盖:当type == GGML_TYPE_F16时返回1e-6,否则回退到test_case::max_nmse_err()。评论中给出的写法为:
double max_nmse_err() override {
if (type == GGML_TYPE_F16) {
// Fused ADDs can keep FP32 intermediates while the CPU rounds each ADD to FP16 (see #28691).
return 1e-6;
}
return test_case::max_nmse_err();
}
- 重新构建并运行同一 ctest 命令,确认
test-backend-ops通过。 - 若该修复尚未合入
master,可暂时在本地应用上述改动以解除 CI 阻塞;不要把它当作 CUDA kernel 修正。
验证方法
重新执行 ctest -C Release --output-on-failure -L 'main|python',确认 test-backend-ops 不再报 ADD_ADD f16/f16 失败。评论中的验证结果:应用该覆盖后完整测试套件为 16449/16449 通过,ADD_ADD 重复运行 20/20 通过。也可以单独重复运行 ADD_ADD f16 用例,观察是否还会出现 NMSE 略高于 1e-7 的偶发失败。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。

![[Bug]: --gpu-device-id has no effect when used with --directml on an AMD GPU](https://www.chat-gpts.plus/wp-content/uploads/2026/09/4024-b3734cdf-768x403.jpg)
