Eval bug: two co-resident llama-server processes (one per GPU) — second replica deterministically dies at ggml-cuda.cu:107 after CUDA graph

这个报错通常出现在同一台机器上同时运行两个 llama-server 进程、每个进程各绑定一块 GPU 的场景;第二个副本(GPU1 上那个)会在 CUDA graph 复用后触发 ggml-cuda.cu:107: CUDA error 并直接退出。优先排查并关闭 CUDA graph,即在启动前

快速结论:这个报错通常出现在同一台机器上同时运行两个 llama-server 进程、每个进程各绑定一块 GPU 的场景;第二个副本(GPU1 上那个)会在 CUDA graph 复用后触发 ggml-cuda.cu:107: CUDA error 并直接退出。优先排查并关闭 CUDA graph,即在启动前设置 GGML_CUDA_DISABLE_GRAPHS=1

适用环境:Windows;官方 Windows CUDA 13.3 x64 发布二进制(build 10750 / b356fa262,Clang 20.1.8);2× NVIDIA GeForce RTX 5060 Ti 16 GB(sm_120,Blackwell),驱动 591.86;AMD Ryzen 7 3700X,128 GB RAM;模型 Qwen3-30B-A3B-Q4_K_M。另有一位报告者在 4× RTX 3060 12GB(sm_86)、驱动 616.86、二进制 b10924 上观察到相关但不相同的退化现象。

最快修复方案:在两个 llama-server 进程启动前设置环境变量 GGML_CUDA_DISABLE_GRAPHS=1。原报告者的鉴别性实验中,关闭 CUDA graphs 后双副本共存的四个服务端日志里 CUDA error 为 0,且不再出现 CUDA Graph id 行,57/58 请求成功。

注意事项:该方案是 Issue 报告中确认有效的规避手段,但并非官方定位到根因后的修复。原报告者测得的吞吐数据在 2 个 block 内波动与两组差距相当,因此只能认为此硬件上“没有明显吞吐损失”,不能据此宣称关闭 graphs 会加速。此外该 -ncmoe 99 配置下 MoE 专家张量在 CPU,双副本共享同一组 CPU 核心,双副本聚合吞吐偏低主要来自 CPU 争用,不能当作 GPU 或 graphs 的性能结论。

问题场景

在同一台 Windows 主机上启动两个相互独立的 llama-server.exe 进程,分别用 -mg 绑定到 GPU0 和 GPU1,端口分别为 8928 和 8929,模型为 Qwen3-30B-A3B-Q4_K_M(-ncmoe 99 -t 4 -c 32768 -np 8)。两个进程各自健康检查通过后,用并发的 cache_prompt: falsen_predict 128temperature 0 请求在两个端口之间轮询,并发量为 N=1/4/8/16。

结果是绑定 GPU1 的第二个副本在 CUDA graph 复用后确定性崩溃;同一轮里 GPU0 进程从不崩溃,单副本进程在相同负载下也从不崩溃。报告者指出,只有在“双副本共存”与“CUDA graphs 开启”两个条件同时满足时才会失败——单独任何一个条件都不足以触发。另一位报告者在 4× RTX 3060、--split-mode tensor、每进程用两块 GPU 的配置下,看到的是第二个实例逐渐退化而非崩溃,同样可通过关闭 graphs 消除。

报错原文

Eval bug: two co-resident llama-server processes (one per GPU) — second replica deterministically dies at ggml-cuda.cu:107 after CUDA graph reuse; GGML_CUDA_DISABLE_GRAPHS=1 fixes it (Windows, 2x RTX 5060 Ti, sm_120)

ggml-cuda.cu:107: CUDA error

CUDA Graph id … reused

原始报告中 CUDA error 的完整错误字符串缺失,原因是进程 abort 时 stderr 输出丢失;报告者表示可以用 unbuffered stderr 重新捕获,但复现是确定性的。

原因分析

最可能的原因是:两个 llama-server 进程在同一主机上共存、又都启用 CUDA graphs 时,graph 复用路径上出现了与 CUDA 上下文/图资源相关的冲突,导致第二个进程在 ggml-cuda.cu:107 处报 CUDA 错误并退出。报告者的 2×2 完整因子实验({单副本, 双副本} × {graphs ON, graphs OFF})显示只有“双副本 + graphs ON”这一格失败,因此两个因素缺一不可。

报告者认为这可能与已有 Issue #27330(CUDA graphs + sm_120 + GGML_CUDA_DISABLE_GRAPHS=1 可完全规避)同源,但可观察现象不同:本 Issue 是双副本、确定性、崩溃并伴随 CUDA error;#27330 是 Linux 上的单副本、随机性(4–15 分钟挂起)、表现为 RC watchdog 挂起并伴随 Xid 8。此处仅为“可能同源”,Issue 中并未给出根因已定位的结论。

另一位报告者的数据点(RTX 3060、--split-mode tensor、4 GPU 分两组)表现为第二个实例的渐进式退化而非崩溃,同样在关闭 graphs 后消失,说明在不同架构上可能存在相关的 CUDA graph / 共存进程故障模式,但可观察症状不同。

环境排查

  • 确认是官方发布的 Windows CUDA 13.3 x64 二进制,并记录 build 与 commit(原文为 build 10750 / b356fa262,sha256 E1EB18C4F13AB9DB48DBED4CD9BD3DC4F94F1E97E4CF4EA53D0FEB2A0E24B26E)。
  • 确认显卡架构与数量:原文为 2× RTX 5060 Ti、16 GB、sm_120(Blackwell);另一位报告者为 4× RTX 3060 12GB、sm_86。
  • 确认 NVIDIA 驱动版本:原文为 591.86;另一位报告者为 616.86。
  • 确认启动参数中每个进程是否用 -mg(或 CUDA_VISIBLE_DEVICES)绑定到各自 GPU,而不是单进程多卡。
  • 确认日志中是否出现 CUDA Graph id … reused,以及 system_infoUSE_GRAPHS = 1
  • 确认 CPU 线程配置:原文是每个副本 -t 4,合计 8 线程;另一位报告者是单进程占两块 GPU。

解决步骤

  1. 先确认问题可复现:同时运行两个 llama-server,分别绑定 GPU0 与 GPU1(例如 -mg 0--port 8928-mg 1--port 8929),用并发请求轮询两个端口,观察第二个副本是否在 CUDA graph 复用后退出并打印 ggml-cuda.cu:107: CUDA error
  2. 在线程/进程启动前设置环境变量 GGML_CUDA_DISABLE_GRAPHS=1,然后以完全相同的参数重启两个 llama-server 进程。
  3. 复查两个服务端日志:确认不再出现 CUDA Graph id 行(说明环境变量已生效),且 CUDA error 计数为 0。
  4. 用与原复现相同的并发梯度(N=1/4/8/16)重新压测两个端口,确认 GPU1 副本不再崩溃、请求不再有一半失败。
  5. 如果关闭 graphs 后仍复现,说明该环境的触发条件与原文不同,需要补充原始日志(含未缓冲 stderr)后再判断,不要继续套用本结论。

验证方法

关闭 graphs 后,若满足以下条件即可认为问题已被规避:两个服务端日志中 CUDA error 计数为 0,且日志里不再出现 CUDA Graph id 行;在双副本并发的各并发档位上不再出现“恰好一半请求失败”的模式(原报告关闭 graphs 后为 57/58 成功,唯一一次 N=8 失败也不带 CUDA 错误)。注意区分客户端伪影:原报告在单副本 N=1 时出现过 ServerDisconnectedError 首次连接抖动,服务端保持存活且不记录 CUDA 错误,不属于本问题。

参考来源

ggml-org/llama.cpp #28404

GamsGo AI

AI 工具推荐

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

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

了解 GamsGo AI

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

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 23066

发表回复

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