快速结论:这个报错通常发生在 llama.cpp 显存/内存分配失败时:ggml_backend_sched_alloc_splits 丢弃了 ggml_gallocr_reserve_n 的返回值,导致 reserve 失败后仍继续执行 ggml_gallocr_alloc_graph,最终从本应返回错误变成段错误(segfault):ggml-backend: discarded ggml_gallocr_reserve_n return value turns an allocation failure into a segfault。优先排查是否在长 prompt、ubatch 较大或显存不足的场景下触发。
适用环境:Issue 中确认的环境为 llama.cpp CUDA 构建,Ubuntu 24.04,驱动 595.71.05,CUDA 13.0.88,2x RTX 3090 24 GiB,54 GiB 主机内存无 swap,CMAKE_CUDA_ARCHITECTURES=86,代码来自 unslothai/llama.cpp 的 qwen4exp/qwen3.8-flash-next 分支 6c5afc8(PR #27742);评论中还确认了 Apple Metal 上的 transcribe.cpp 复现路径。
最快修复方案:暂无确认的一步修复方案;Issue 中的修复思路是把 ggml/src/ggml-backend.cpp:1586 处的 ggml_gallocr_reserve_n 调用包进 if (!...) 判断并返回 false,使失败走 GGML_STATUS_ALLOC_FAILED 错误路径,相关 PR 为 #27855;该修复思路在提交时尚未验证。
注意事项:该改动只解决“分配失败被吞掉后变成 segfault”,不会降低显存占用,也不会让原本 OOM 的配置变得可用;作者明确说明该补丁未经运行验证,只是阅读周边代码后的提案。评论中列出多个相关 PR(#26070、#27855、#28149),需要等待合并确认。
问题场景
用户在 llama.cpp 的 llama-server 上运行 Qwen3.8-Flash-Next(PR #27742,qwen4exp),使用 2x RTX 3090,将 routed experts 拆分到两张卡和主机内存。服务能正常加载,短 prompt 能正确回答,但在处理长 prompt 时中途崩溃。复现三次分别发生在 17849、26624 和 59392 tokens,涉及两种不同的 expert 放置方式,以及 -ub 2048 和 -ub 1024 两种配置。
报错原文
prompt processing, n_tokens = 17849, progress = 0.90, t = 36.54 s / 488.50 tokens per second
ggml_backend_cuda_buffer_type_alloc_buffer: allocating 1599.01 MiB on device 1: cudaMalloc failed: out of memory
ggml_gallocr_reserve_n_impl: failed to allocate CUDA1 buffer of size 1676685440
Segmentation fault
ggml-backend: discarded ggml_gallocr_reserve_n return value turns an allocation failure into a segfault
原因分析
最可能的原因是 ggml/src/ggml-backend.cpp:1586 处的 ggml_gallocr_reserve_n 调用没有检查返回值。该函数声明为 bool,并在 ggml-alloc.h:64 中说明缓冲区分配失败时返回 false。当 CUDA 分配失败时,reserve 操作让 allocator 处于部分初始化状态,代码却继续调用 ggml_gallocr_alloc_graph,最终触发段错误,而不是通过已有错误路径返回。相同调用在 ggml-backend.cpp:1929 处有检查,只有 line 1586 丢弃了返回值。
另一个促成因素是 qwen4exp 的 sparse attention bias 输入大小为 [n_kv, n_tps, n_stream],因此 compute buffer 会随实际处理的 prompt 长度增长,而不是随 -c 增长。这意味着一套能正常加载、能回答短 prompt 的配置,仍可能在长 prompt 时耗尽显存,然后从“报错”变成“段错误”。
环境排查
- 确认 llama.cpp 构建来源与 commit:Issue 中为
unslothai/llama.cpp分支qwen4exp/qwen3.8-flash-next,commit6c5afc8(PR #27742)。 - 确认 CUDA 构建配置:CUDA 13.0.88(构建描述中另提到 13.0.2)、
CMAKE_CUDA_ARCHITECTURES=86。 - 确认显卡与显存:2x RTX 3090,每张 24 GiB,主机 RAM 54 GiB,无 swap。
- 确认操作系统与驱动:Ubuntu 24.04,驱动 595.71.05。
- 确认运行参数:
-ngl 99 -sm layer -fit off -c 32768 -fa on -ctk f16 -ctv f16 -b 2048 -ub 2048 -t 8,以及-ot指定的 CPU 卸载规则。 - 如果使用 Apple Metal,评论中确认在
transcribe.cpp上也能复现类似 OOM 崩溃,涉及 Metal buffer 分配失败。
解决步骤
- 先确认触发条件:是否在长 prompt 处理过程中、显存接近耗尽时出现
cudaMalloc failed: out of memory或 Metal 的failed to allocate buffer,随后进程直接崩溃且没有Compute error.之类的错误输出。 - 降低显存压力作为临时规避:减少
-c、降低-ub、调整-ot将更多层放到 CPU,或减少并发/批量处理,避免在长 prompt 时触发分配失败。 - 可优先尝试 Issue 中提出的代码修复:在
ggml/src/ggml-backend.cpp:1586处把ggml_gallocr_reserve_n(...)包进if (!...)判断,失败时记录failed to reserve graph并return false,让错误走GGML_STATUS_ALLOC_FAILED路径,而不是继续进入ggml_gallocr_alloc_graph。 - 关注相关 PR 的合并状态:评论中列出了 #26070、#27855、#28149,并建议合并为一个经过审查的补丁;在合并前不要把该修复当成已发布的稳定行为。
- 如果需要在本地验证修复方向,按 Issue 中的 repro 构建相应分支,并发送约 18000 tokens 的 prompt 来触发;注意该补丁本身不改变显存占用,只是把崩溃变成可处理的分配失败错误。
验证方法
应用修复后,再次触发相同的长 prompt 分配失败场景,预期不再出现 Segmentation fault,而是看到 failed to reserve graph 或 failed to allocate graph 之类的错误日志,并通过 llama.cpp 已有错误路径返回 GGML_STATUS_ALLOC_FAILED,最终在 server 侧表现为 Compute error. 并释放槽位,而不是进程直接崩溃。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。
![[Bug]: Incorrect TPM limiting for virtual keys](https://www.chat-gpts.plus/wp-content/uploads/2026/09/24677-3bec262a-768x403.jpg)
![[Bug]: Responses WebSocket drops deployment-level default request parameters](https://www.chat-gpts.plus/wp-content/uploads/2026/09/33448-1673fc31-768x403.jpg)
