Misc. bug: ggml_top_k() CUDA CUB implementation runs out of memory for large tensors

用户使用 llama-cli 的测试工具 test-backend-ops 运行 TOP_K 操作测试时触发。具体命令如下:

Misc. bug: ggml_top_k() CUDA CUB implementation runs out of memory for large tensors

Misc. bug: ggml_top_k() CUDA CUB implementation runs out of memory for large tensors

快速结论:该报错发生在 llama.cpp 的 CUDA 后端运行 ggml_top_k() 操作处理超大张量(如 ne=[843776,8192,1,1])时,由于 CUDA CUB 临时缓冲区分配方式不合理,即使在拥有近 100 GiB 显存的 NVIDIA RTX PRO 6000 显卡上也会触发 OOM。优先排查 ggml_top_k 的 CUDA CUB 实现中临时缓冲区分配逻辑

问题场景

用户使用 llama-cli 的测试工具 test-backend-ops 运行 TOP_K 操作测试时触发。具体命令如下:

./bin/test-backend-ops -o "TOP_K(type=f32,ne=[843776,8192,1,1],k=2048,ties=0)" -j 32

该测试在 CUDA 后端下执行,目标张量尺寸为 843776 x 8192(约 6.9B 个 float32 元素),需要从中选出 top-2048 个值。用户使用的显卡为 NVIDIA RTX PRO 6000 Blackwell Max-Q Workstation Edition,显存 97247 MiB,仍然触发 OOM。

报错原文

CUDA error: out of memory
  current device: 0, in function alloc at /home/phm/projects/llama.cpp/ggml/src/ggml-cuda/ggml-cuda.cu:528
  cuMemCreate(&handle, reserve_size, &prop, 0)

此报错发生在版本 9294 (0f3cb3fc8) 和 9683 (8086439a4) 中,均在 test-backend-ops 执行时复现。当调用 cuMemCreate 分配设备内存时,CUDA 返回 out of memory。

原因分析

Issue 指出,CUDA CUB 的 ggml_top_k() 实现存在临时缓冲区分配策略问题。在处理超大张量时,CUB 库需要为 DeviceSegmentedRadixSort 或类似操作分配大量临时显存。当前实现没有对临时缓冲区的尺寸进行合理限制或分块处理,导致一次性申请的内存超过可用显存,即使物理总显存高达 97 GiB 也无法满足。

可能原因包括:

  • CUB 的临时缓冲区大小估算过于保守,与实际所需内存不匹配。
  • 当前实现没有利用“显存较大但仍有限”的条件进行分块或流式处理。
  • Tensor 的 ne[1]=8192(即 8192 个独立的行/片段)导致 CUB 需要为每个片段分别准备临时空间,累计后远超可用内存。

环境排查

  • 确认 llama.cpp 版本:复现版本为 9294 (0f3cb3fc8) 和 9683 (8086439a4),建议检查是否包含相关修复提交。
  • 确认 CUDA 版本:用户未明确提供,但根据 compute capability 12.0 推断,至少需要 CUDA 12.x 以支持 Blackwell 架构。
  • 确认 显卡型号和显存:RTX PRO 6000 Blackwell Max-Q,显存 97247 MiB,空闲 96640 MiB。如果显存更小(如 24 GiB 或 48 GiB),OOM 更容易触发。
  • 确认 测试命令参数ne=[843776,8192,1,1],k=2048 是触发条件,更小的张量可能正常工作。

解决步骤

  1. 检查是否已应用修复补丁:查看 llama.cpp 仓库的 git log,确认是否有针对 ggml_top_k CUDA CUB 临时缓冲区分配的优化提交。建议 pull 最新代码或 revert 到已知可用的稳定版本(如 9294 之前的 commit)。
  2. 尝试减小张量尺寸或 k 值:作为临时规避,可以减少 ne[0]ne[1] 的尺寸,或降低 k 值(例如从 2048 降到 1024),观察是否还会 OOM。
  3. 尝试使用 CPU 后端运行测试:如果不需要 CUDA 加速且仅用于验证,可以指定 CPU 后端:
    ./bin/test-backend-ops -o "TOP_K(type=f32,ne=[843776,8192,1,1],k=2048,ties=0)" -j 32 -b CPU

    这样可避免 CUDA CUB 的实现问题。

  4. 禁用 CUDA 的 CUB 实现:在编译 llama.cpp 时,尝试添加 -DGGML_CUDA_CUB=OFF 选项以禁用 CUB 加速,回退到更朴素但可能更节省显存的 top_k 实现。这是 可优先尝试的解决方案:
    cmake -B build-cuda -DGGML_CUDA=ON -DGGML_CUDA_CUB=OFF ..
  5. 提交 Issue 或等待修复:如果上述步骤均无法解决,且该问题对你的工作流至关重要,建议在 llama.cpp 仓库提交 Issue(或关注已有 Issue #24718)以跟踪社区修复进度。

验证方法

重新运行触发命令:

./bin/test-backend-ops -o "TOP_K(type=f32,ne=[843776,8192,1,1],k=2048,ties=0)" -j 32

如果不再报 CUDA error: out of memory 且测试正常完成(输出测试通过信息),则说明问题已解决。确认时需注意显存占用是否稳定在可用范围内。

参考来源

ggml-org/llama.cpp #24718

GamsGo AI

AI 工具推荐

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

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

了解 GamsGo AI

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

celebrityanime
celebrityanime
文章: 12192

发表回复

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