Eval bug: CUDA crash on tensor copy

用户运行 llama-server 进行多卡(2× NVIDIA RTX 5070 Ti)推理,使用 -c 160000 (长上下文)和 -ctk q8_0 -ctv q8_0 (量化缓存),并在升级到 NVIDIA 驱动 590 和 CUDA 13.1 后触发。同时,运行 test-backend

Eval bug: CUDA crash on tensor copy

Eval bug: CUDA crash on tensor copy

快速结论:该报错通常发生在使用 llama.cpp 的多 GPU 推理场景(如双 RTX 5070 Ti)或 CUDA 图模式(CUDA graph)下,报错 cudaMemcpyPeerAsync 超时或 cudaGraphExecUpdateFailure。优先排查 CUDA 驱动版本(590)与 llama.cpp 的兼容性,以及较长的上下文长度(-c 160000)是否导致设备间张量拷贝超时。

问题场景

用户运行 llama-server 进行多卡(2× NVIDIA RTX 5070 Ti)推理,使用 -c 160000(长上下文)和 -ctk q8_0 -ctv q8_0(量化缓存),并在升级到 NVIDIA 驱动 590 和 CUDA 13.1 后触发。同时,运行 test-backend-ops 时也会失败,涉及 SOFT_MAX 操作以及 CUDA 图更新失败(cudaGraphExecUpdateFailure)。

报错原文

/devel/tools/llama.cpp/ggml/src/ggml-cuda/ggml-cuda.cu:97: CUDA error
CUDA error: the launch timed out and was terminated
  current device: 1, in function ggml_backend_cuda_cpy_tensor_async at /devel/tools/llama.cpp/ggml/src/ggml-cuda/ggml-cuda.cu:2836
  cudaMemcpyPeerAsync(dst->data, cuda_ctx_dst->device, src->data, cuda_ctx_src->device, ggml_nbytes(dst), cuda_ctx_src->stream())

除主报错外,compute-sanitizer 中还观察到:

Program hit cudaErrorGraphExecUpdateFailure (error 910) due to "the graph update was not performed because it included changes which violated constraints specific to instantiated graph update"

kernel log 中的 GPU 锁定信息:

NVRM: krcWatchdog_IMPL: RC watchdog: GPU is probably locked!  Notify Timeout Seconds: 7
NVRM: Xid (PCI:0000:06:00): 8, pid=4307, name=llama-server, channel 0x00000008

原因分析

可能原因:

  • CUDA 图更新冲突:当 llama.cpp 使用 CUDA graph 加速时,图捕获后的参数变化(如 tensor shape 或数据类型)可能导致 cudaGraphExecUpdateFailure(error 910),进而破坏后端状态,最终在异步张量拷贝时表现为超时。
  • 多 GPU 间 Peer-to-Peer 超时:长上下文(-c 160000)导致张量尺寸过大,cudaMemcpyPeerAsync 在设备间拷贝时被 GPU watchdog 打断(从 dmesg 中可确认 watchog 主动超时)。
  • 驱动/CUDA 版本变化:用户明确提到升级到驱动 590 和 CUDA 13.1 后首次出现。虽然其他用户在相同版本下未遇到问题(I’ve been using 590 with 13.1 for quite a while without issues),但驱动或 CUDA 版本的变化可能改变调度行为,与特定硬件组合(RTX 5070 Ti + 双卡)交互时暴露缺陷。

环境排查

  • llama.cpp 版本:确认当前 commit 是否包含 2cd20b72ed3565ac6935911ca0d9b5d73ae70d0d。
  • CUDA 驱动版本:检查当前驱动是否为 590,CUDA 工具包是否 13.1。
  • 显卡型号及数量:双 NVIDIA RTX 5070 Ti,compute capability 12.0。
  • 上下文长度-c 160000 是否过大导致多 GPU 数据传输量超过限制。
  • 后端启动日志:确认 ggml_cuda_init 是否成功识别全部 GPU,且 VMM: yes

解决步骤

  1. 更新 llama.cpp 到包含特定 commit 的版本:Issue 中提及了一个可能的修复 commit:2cd20b72ed3565ac6935911ca0d9b5d73ae70d0d。但用户指出即使包含了该 commit 问题依然复现,说明该 commit 未完全修复此问题。但仍建议确保代码为最新主分支或包含最新 CUDA 相关修复。
  2. 缩短上下文长度:可优先尝试将所有上下文长度参数(如 -c 从 160000)降低,例如 32768 或更低,以减小单次 cudaMemcpyPeerAsync 的数据量,避免 GPU watchdog 超时。
  3. 关闭 CUDA graph:如 SDL 日志中频繁出现 cudaGraphExecUpdateFailure,可尝试在启动时关闭 CUDA Graph 优化(如果 llama.cpp 支持,例如通过环境变量 GGML_CUDA_DISABLE_GRAPHS=1 或在代码中关闭),避免图更新失败导致的后端不一致。
  4. 回滚驱动与 CUDA 版本:如果问题仅在驱动 590 + CUDA 13.1 下出现,优先回滚到已知稳定的驱动版本(例如 550)和 CUDA 12.x(如 12.4)。该步骤在 Issue 中虽然未直接给出解决方案,但用户日志明确将版本升级列为变量。
  5. 排查单一 GPU 模式:若条件允许,可改为单 GPU 运行(如通过 --main-gpu--tensor-split 将全部 tensor 分配到一个 GPU),确认是否与多 GPU 张量拷贝逻辑相关。
  6. 运行 compute-sanitizer(备选):使用 compute-sanitizer test-backend-ops 检查 SOFT_MAX 等特定操作的失败是否与 CUDA 图或张量操作有关。如果 SOFT_MAX 测试始终失败,可能涉及算数逻辑问题而非单纯的超时。

验证方法

  • 再次启动 llama-server,观察是否在启动后短时间内复现 cudaMemcpyPeerAsync 超时报错。
  • 检查 dmesg 不再出现 NVRM: krcWatchdog_IMPL: RC watchdog: GPU is probably locked! 条目。
  • 运行 test-backend-ops 确保所有测试通过(至少 CUDA 后端不报 FAIL)。

参考来源

ggml-org/llama.cpp #20146

GamsGo AI

AI 工具推荐

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

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

了解 GamsGo AI

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

celebrityanime
celebrityanime
文章: 13617

发表回复

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