Misc. bug: [SYCL] CPY to q4_1/q5_1/q8_0 doesn’t match CPU reference

在使用 SYCL 后端(test-backend-ops -o CPY)测试 f16/bf16 到 q4_1/q5_1/q8_0 的量化拷贝时,CPU 参考实现与 GPU 实现因舍入行为不一致而随机报错;应优先对齐 CPU 与 SYCL 两侧的量化舍入逻辑,而不是只调一个编译开关。

快速结论:在使用 SYCL 后端(test-backend-ops -o CPY)测试 f16/bf16 到 q4_1/q5_1/q8_0 的量化拷贝时,CPU 参考实现与 GPU 实现因舍入行为不一致而随机报错;应优先对齐 CPU 与 SYCL 两侧的量化舍入逻辑,而不是只调一个编译开关。

适用环境:llama.cpp master d327bf1f0(含 PR #31120),icpx 2025.3.3(oneAPI)编译,-DGGML_SYCL=ON -DGGML_SYCL_TARGET=INTEL,Release 构建;Linux(Ubuntu 24.04)、Intel Arc B580 12GB、i5-13400、NEO 26.35.39758.10。讨论中还出现了 B70 的测试数据,但未给出完整环境。

最快修复方案:暂无确认的一步修复方案。讨论中可优先尝试的是:在 CPU 参考构建中加入 -fp-model=precise,并让 SYCL 侧采用与 PR #31120 相同的小型舍入辅助实现;讨论中的实验显示这样可让 q4_1、q5_1 在 50 次运行中 0 失败,但 q8_0 仍需额外对齐 AVX2 量化路径才会归零。

注意事项:上述修复方案来自 Issue 评论中的复现实验,并非官方已合并的修复;-fp-model=precise 单用不能解决问题,甚至可能放大失败率(讨论中 50 次失败 45 次)。q4_1/q5_1 的本质是 x.5 舍入歧义,而 q8_0 涉及“应匹配参考实现还是匹配 x86 AVX2 路径”,取决于目标平台,尚无统一结论。

问题场景

用户在 Linux 上用 icpx 2025.3.3 构建启用 SYCL 后端的 llama.cpp,并反复执行 test-backend-ops -o CPY -b SYCL0,测试 f16/bf16 到 q4_1、q5_1、q8_0 的 CPY(量化拷贝)算子。PR #31120 修好了 q2_0、q4_0、q5_0 的同类问题,剩余三个量化类型仍会随机失败,本质仍是 1 ulp 级别的舍入差异。用户还在讨论中尝试了 test-backend-ops -o CPY -p 'type_dst=(q4_1|q5_1|q8_0)',每组合运行 50 次。

报错原文

test-backend-ops -o CPY -b SYCL0
Misc. bug: [SYCL] CPY to q4_1/q5_1/q8_0 doesn't match CPU reference

100 runs with #31120 applied: q4_1 15 failed, q8_0 11, q5_1 9. All three fail on master too.

原因分析

可能原因是 CPU 与 GPU 两侧的浮点舍入行为不一致。量化时像 0.499999998、0.5、0.5000001 这样的值会被映射到 0 或 1,具体取决于编译器的浮点优化行为,因此同一输入在 CPU 参考实现和 SYCL 设备端可能落到不同结果。讨论中进一步确认:icx 默认的快速浮点模式连 CPU 参考本身都会偏移,于是两侧在 GPU 代码运行之前就已经不一致;即使给两侧都加上 -fp-model=precise,仍大量失败,说明仅靠编译开关不够。q4_1 与 q5_1 属于同一种 1 ulp 舍入问题;q8_0 则是另一条路径问题:x86 AVX2 的 CPU 量化用的是 127/amax 配合 round half to even,而不是参考量化器的 1/(amax/127) 配合 roundf,SYCL 端尚未匹配该行为。

环境排查

  • 确认 llama.cpp 版本是否为 master d327bf1f0,以及是否已应用 PR #31120。
  • 确认构建参数:-DGGML_SYCL=ON -DGGML_SYCL_TARGET=INTEL,Release 模式。
  • 确认编译器为 icpx 2025.3.3(oneAPI),并记录 CPU 参考构建所使用的编译器与浮点选项(默认 fast 还是 -fp-model=precise)。
  • 确认操作系统为 Ubuntu 24.04、GPU 为 Intel Arc B580 12GB、CPU 为 i5-13400、驱动为 NEO 26.35.39758.10。
  • 确认测试是否包含 x.5 边界输入;f32 源类型在讨论中各变体均为 0 失败,可先用它区分是量化舍入问题还是其他路径问题。

解决步骤

  1. 先按原命令复跑以建立基线:test-backend-ops -o CPY -b SYCL0,重点观察 q4_1、q5_1、q8_0 的失败是否随机出现。
  2. 用类型过滤缩小范围:test-backend-ops -o CPY -p 'type_dst=(q4_1|q5_1|q8_0)',每组多跑几次,记录各类型失败次数(讨论中 #31120 后 100 次为 q4_1 15、q8_0 11、q5_1 9)。
  3. 检查 CPU 参考构建的浮点选项。单加 -fp-model=precise 并不可靠(讨论中 50 次失败 45 次),需要与代码层面的舍入修正配合。
  4. 可优先尝试:在 SYCL 侧引入与 PR #31120 相同的小型舍入辅助函数,同时让 CPU 参考以 -fp-model=precise 构建。讨论中该组合使 q4_1、q5_1 达成 50 次 0 失败,仅剩 f16->q8_0 失败 6 次。
  5. 处理 q8_0:让 SYCL 端匹配 x86 AVX2 的量化行为(127/amax、round half to even);讨论中该组合在 x86 上达成 50 次 0 失败。
  6. 若目标是 ARM 或非 AVX 平台,需要另行确认是匹配参考量化器还是匹配 AVX2 路径,这两者行为不同,不要混用结论。

验证方法

用同样的 test-backend-ops -o CPY -p 'type_dst=(q4_1|q5_1|q8_0)' 连续运行多轮(讨论中采用每组合 50 次),确认 q4_1、q5_1、q8_0 的失败次数为 0;同时用 f32 源类型确认没有引入新失败。若在 x86 AVX2 平台,验证标准应对齐 AVX2 路径;在其他平台则需与目标参考量化器比对后再判定通过。

参考来源

ggml-org/llama.cpp #31140

GamsGo AI

AI 工具推荐

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

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

了解 GamsGo AI

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

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 33488

发表回复

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