Eval bug: SYCL crash in ggml_sycl_pool_vmm::free – oneDNN scratchpad breaks LIFO pool order

该报错通常出现在 llama.cpp 使用 SYCL 后端、同时启用 oneDNN 与 VMM 并跑 MUL_MAT_ID 融合算子或 llama-bench 的场景下。优先排查 oneDNN scratchpad 是否占用了 SYCL VMM 的 LIFO 池栈顶,导致 buffer 释放时断言失

快速结论:该报错通常出现在 llama.cpp 使用 SYCL 后端、同时启用 oneDNN 与 VMM 并跑 MUL_MAT_ID 融合算子或 llama-bench 的场景下。优先排查 oneDNN scratchpad 是否占用了 SYCL VMM 的 LIFO 池栈顶,导致 buffer 释放时断言失败。

适用环境:llama.cpp 0.4.0-dev(build 10879,commit 9cf3bf256),Clang 24.0.0,Linux x86_64,SYCL 后端,Intel Arc Pro B70,Level Zero 26.22.38646.6-1~24.04~ppa1(后续测试升级到 26.31.39395.13 问题依旧),oneDNN 3.14.0,intel/llvm bf6137c1d65cdb709203da6a05a1f031bb65c5bb。必须满足 GGML_SYCL_DNNL: yes、GGML_SYCL_SUPPORT_VMM: yes,以及 GGML_SYCL_ENABLE_DNN: 1、GGML_SYCL_ENABLE_VMM: 1。

最快修复方案:暂无确认的一步修复方案。Issue 中有修复 PR(#27689)但未合并,且该 PR 覆盖的是另一个场景,不代表能解决本 Issue 中 get_size() > 0 的情况。

注意事项:该问题与驱动版本无关,从 26.22 升级到 26.31 后仍可复现;其他 Arc 770 / B60 环境下未能复现,说明还可能与具体硬件或 oneDNN kernel 选择路径有关。SYCL CI 目前只编译不运行测试,因此该 bug 不会被自动拦截。

问题场景

在 Linux 上使用 llama.cpp 的 SYCL 后端,并且构建时同时启用 oneDNN(GGML_SYCL_DNNL)与 VMM(GGML_SYCL_SUPPORT_VMM),运行时设置 GGML_SYCL_ENABLE_DNN=1 与 GGML_SYCL_ENABLE_VMM=1。此时执行以下任一操作可能触发崩溃:

  • 运行 SYCL 后端单元测试:./test-backend-ops test -b SYCL0 -o MUL_MAT_ID_FUSION -p "type_a=f32,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=512,k=2048,o=1,mul=1"
  • 运行 llama-bench,例如使用 Qwen2.5-1.5B-Q4_K_M:llama-bench -m <model> -r 1 --no-warmup -p 0 -n 0 -pg 1024,128 --device SYCL0 -ngl 999

触发路径位于 ggml-sycl.cpp 的 ggml_sycl_mul_mat_id 中,在分配三个 buffer(约 5151-5167 行)后,某个 buffer 的析构函数触发断言。oneDNN 与 VMM 必须同时启用,且 oneDNN 需要选择 matmul kernel 并申请 scratchpad。

报错原文

ggml/src/ggml-sycl/ggml-sycl.cpp:1857: GGML_ASSERT(ptr == reinterpret_cast<void *>(pool_addr + pool_used)) failed

Eval bug: SYCL crash in ggml_sycl_pool_vmm::free - oneDNN scratchpad breaks LIFO pool order

原因分析

最可能的原因是 oneDNN 的 scratchpad 内存被 backend 的 context 全局持有,get_scratchpad_mem 分配后从不释放,其内存块一直停留在 ggml_sycl_pool_vmm 这个 LIFO 栈的栈顶。当 ggml_sycl_mul_mat_id 中三个 buffer 之一被析构、调用 free 时,期望释放的指针并不是池顶的实际地址,于是 GGML_ASSERT(ptr == pool_addr + pool_used) 失败。

问题的时间线:PR #12097 引入 get_scratchpad_mem 时分配合乎当时的逻辑;PR #17095 增加了 test_mul_mat_id_fusion 测试,但 SYCL CI 未运行测试;PR #22862 加入 ggml_sycl_pool_vmm 并默认启用 VMM(g_ggml_sycl_enable_vmm = 1),此后 LIFO 不变量被破坏,而测试未能拦截。Issue 作者已确认,升级驱动不能解决该问题,因为这是 LIFO 池序被破坏导致的逻辑缺陷。

环境排查

  • 确认 llama.cpp 版本:0.4.0-dev(build 10879,commit 9cf3bf256)。
  • 确认 SYCL 后端编译宏:GGML_SYCL_DNNL: yes、GGML_SYCL_SUPPORT_VMM: yes。
  • 确认运行时环境变量:GGML_SYCL_ENABLE_DNN: 1、GGML_SYCL_ENABLE_VMM: 1(两者缺一通常无法触发)。
  • 确认 matmul 是否真的申请了 scratchpad:可用 llama-bench -v 查看上述宏与变量,Issue 中另提供了一个给 gemm.hpp 打补丁打印 “bug condition occurred, scratchpad size is …” 的方法用于确认走进问题代码路径。
  • 确认 GPU 型号与驱动:Intel Arc Pro B70,Level Zero 26.22.38646.6 与 26.31.39395.13 均可复现。
  • 确认 oneDNN 版本与 intel/llvm 编译器版本,oneDNN 3.14.0 与 intel/llvm bf6137c1d65cdb709203da6a05a1f031bb65c5bb 下可复现。

解决步骤

  1. 先确认构建与运行环境是否满足触发条件:GGML_SYCL_DNNL、GGML_SYCL_SUPPORT_VMM 均为 yes,且 GGML_SYCL_ENABLE_DNN=1、GGML_SYCL_ENABLE_VMM=1。不满足时通常不会触发该断言。
  2. 用上述 test-backend-ops 命令或 llama-bench 命令复现,确认能否稳定触发 ggml_sycl_pool_vmm::free 处的断言。
  3. 如果需要在同型号硬件上判断是否走进问题路径,可按 Issue 提供的补丁给 gemm.hpp 加入 scratchpad 大小日志,观察是否出现 “bug condition occurred, scratchpad size is …” 输出。
  4. 关注并评估 PR #27689:该 PR 提到了同样的断言,但只覆盖新增代码对应的情况,不覆盖 master 上已存在的 get_size() > 0 分支,因此可优先尝试,但不保证能解决本 Issue。若该分支未修复就仍会复现。
  5. 在确有修复合并前,可优先尝试回退或关闭 VMM(注意:Issue 中未给出具体环境变量组合,且未验证关闭后是否仍触发),或者改用非 SYCL 后端,以避免走进该 LIFO 池释放路径。

验证方法

重新运行 Issue 中给出的 test-backend-ops 命令与 llama-bench 命令,若不再出现 ggml-sycl.cpp:1857 的 GGML_ASSERT(ptr == …) 断言,且两次测试均正常完成,可认为问题已解决。若使用补丁方式观察,也可以确认不再输出 “bug condition occurred, scratchpad size is …” 日志。注意:在 Arc 770 / B60 等未复现的机器上,即使相同命令通过也不代表该 LIFO 缺陷被修复。

参考来源

ggml-org/llama.cpp #28660

GamsGo AI

AI 工具推荐

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

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

了解 GamsGo AI

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

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 23335

发表回复

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