
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是触发条件,更小的张量可能正常工作。
解决步骤
- 检查是否已应用修复补丁:查看 llama.cpp 仓库的 git log,确认是否有针对
ggml_top_kCUDA CUB 临时缓冲区分配的优化提交。建议 pull 最新代码或 revert 到已知可用的稳定版本(如 9294 之前的 commit)。 - 尝试减小张量尺寸或 k 值:作为临时规避,可以减少
ne[0]或ne[1]的尺寸,或降低k值(例如从 2048 降到 1024),观察是否还会 OOM。 - 尝试使用 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 的实现问题。
- 禁用 CUDA 的 CUB 实现:在编译 llama.cpp 时,尝试添加
-DGGML_CUDA_CUB=OFF选项以禁用 CUB 加速,回退到更朴素但可能更节省显存的 top_k 实现。这是 可优先尝试的解决方案:cmake -B build-cuda -DGGML_CUDA=ON -DGGML_CUDA_CUB=OFF .. - 提交 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 且测试正常完成(输出测试通过信息),则说明问题已解决。确认时需注意显存占用是否稳定在可用范围内。



