[Bug][HiSparse] Decode engine dies with cudaErrorLaunchFailure in the host-mirror path under sustained P/D host imports

该报错出现在 vLLM 的 NIXL P/D 部署中启用 HiSparse(decode 端 KV connector)并让导入的前缀持续落到 pinned host pool 时,decode engine 会抛出 sticky 的 CUDA error: unspecified launch f

快速结论:该报错出现在 vLLM 的 NIXL P/D 部署中启用 HiSparse(decode 端 KV connector)并让导入的前缀持续落到 pinned host pool 时,decode engine 会抛出 sticky 的 CUDA error: unspecified launch failure,所有 TP worker 在同一步骤失败且引擎无法恢复。优先排查 HiSparse 在 FULL CUDA graph replay 下对 host-mirror 状态的同步问题。

适用环境:Issue 中确认的环境为 vLLM PR #55398 head(abde160237),HiSparse connector 在该 PR stack 上(main 上尚不存在);硬件 2 节点 × 8 B200,1P(TP8) + 1D(TP8),NIXL pull connector over IB;block size 64;NCCL_NET_PLUGIN=none。另有报告者补充在 vLLM 0.30.0(ced6857afa0e)上,GLM-5.3、8×B300 与 8×H200、TP8、FP8 KV、启用 CUDA graphs、MTP 关闭时也观察到同类报错,但该环境尚未确认相同根因。

最快修复方案:暂无确认的一步修复方案。Issue 中已尝试在 decode engine 设置 CUDA_LAUNCH_BLOCKING=1,但只是把 fault 定位到了 FULL CUDA graph replay,并未阻止崩溃(3/3 复现)。

注意事项:Issue 作者最终以“无法复现”关闭(Closed,2026-10-06),并说明如果 TOT 上仍复现可重新打开。评论中提出的 host 内存注册(cudaHostUnregister()/NIXL-UCX 注册交接)相关性、以及 #56158 是否能消除崩溃,均未被验证或已撤回,只能作为排查方向,不要当作已确认结论。

问题场景

用户在 NIXL P/D(prefill/decode 分离)部署中,于 decode engine 启用 HiSparse connector(MultiConnector 组合 NixlConnector + HiSparseConnector,host_pool_gib:128),并通过一行本地改动把 pull_scheduler.py 中的 request.hisparse_gpu_import 强制置为 False,使每个导入的前缀都走 pinned host pool(host-mirror)路径。负载经过 P/D proxy,ISL 32000 / OSL 2000,按并发 1→2→4→8→16 的 ramp 递增,使用非重复 prompt。

复现需要两个条件同时满足:持续 host import 的 traffic ramp,以及一定长度的输出。Issue 中两次尝试两次复现,每次约 35 分钟 engine 时间后崩溃;在 C16 失败前已完成约 40 个请求。直接从 C16 冷启动、OSL 500 的测试 32/32 全部通过,说明短输出和无预热不会触发。

报错原文

[Bug][HiSparse] Decode engine dies with cudaErrorLaunchFailure in the host-mirror path under sustained P/D host imports

File "vllm/v1/worker/gpu/model_runner.py", line 1928, in execute_model
  self.kv_connector.finish_forward()
File "vllm/v1/worker/gpu/kv_connector.py", line 96, in finish_forward
File "vllm/distributed/kv_transfer/kv_connector/v1/multi_connector.py", line 310, in finish_forward
File "vllm/distributed/kv_transfer/kv_connector/v1/hisparse/connector.py", line 247, in finish_forward
File "vllm/distributed/kv_transfer/kv_connector/v1/hisparse/worker.py", line 831, in finish_forward
  self._finish_mirror_phase(self._forward_ready_event)
File "vllm/distributed/kv_transfer/kv_connector/v1/hisparse/worker.py", line 823, in _finish_mirror_phase
  state.event.synchronize()
torch.AcceleratorError: CUDA error: unspecified launch failure

File "vllm/v1/worker/gpu/model_runner.py", line 1887, in execute_model
  model_output = self.cudagraph_manager.run_fullgraph(batch_desc)
File "vllm/v1/worker/gpu/cudagraph_utils.py", line 667, in run_fullgraph
  super().run_fullgraph(desc)
File "vllm/v1/worker/gpu/cudagraph_utils.py", line 486, in run_fullgraph
  self.graphs[desc].replay()
torch.AcceleratorError: CUDA error: unspecified launch failure

原因分析

Issue 中的定位经历了两个阶段:

第一,未设置 CUDA_LAUNCH_BLOCKING=1 时,故障被收集在 _finish_mirror_phase 的 event.synchronize() 处,另有第二个 worker 在同一步骤的 gpu/async_utils.py:168 copy_event.synchronize() 处独立失败。该位置只是异步 launch 失败被收集的点,不一定是真正出错的 kernel。

第二,加上 CUDA_LAUNCH_BLOCKING=1 后故障转移到更具体的位置:FULL CUDA graph replay 内部的 self.graphs[desc].replay(),即 faulting work 位于被 replay 的 graph 内部。这让 Issue 作者认为 #56158 是最强线索:HiSparseRuntime.finish_kv_update(vllm/v1/hisparse/runtime.py:973)在 cudagraph_runtime_mode == CUDAGraphMode.FULL 时会显式跳过 submit_layer_mirror(),正是 PR 描述的那种 “mirror state under FULL replay” 的缺口。

可能的其他方向:评论区有人提出后续 commit c597b2c 引入的 cudaHostUnregister() 是否与 NIXL/UCX 的注册交接有关,因为 replayed 的 HiSparse kernel 同样会访问 host pool,仅凭 fault 落在 graph replay 内部不足以排除 host-memory mapping 问题;但作者已撤回该线索(rcache 测试为负,且时间上早于本次归因)。另有报告者在无 NIXL 的单节点 colocated P/D、HiSparseConnector + OffloadingConnector 下观察到相似报错,但未确认同一根因。

注意:Issue 在被关闭时作者表示无法复现,因此上述归因属于当时的最可能方向,不是已验证的根因结论。

环境排查

  • 确认 vLLM 版本或 PR 栈:Issue 使用 PR #55398 head abde160237;HiSparse connector 在当时的 main 上不存在,如果你不在该 PR stack 上,问题表现可能不同。
  • 确认是否为 NIXL P/D 部署:是否使用 NixlConnector(producer/consumer)以及 MultiConnector 组合 HiSparseConnector。
  • 确认 decode 端 host_pool_gib 配置(Issue 为 128)以及导入前缀是否走 host path。
  • 确认 block size:Issue 要求 64,128 会命中该路径上无关的既有缺陷。
  • 确认 NCCL_NET_PLUGIN=none 是否在两个 engine 上一致设置。
  • 确认负载模式:是否为 ramp 递增并发、较长 OSL(Issue 为 ISL 32000 / OSL 2000),因为短输出与冷启动不触发。
  • 排查时可临时设置 CUDA_LAUNCH_BLOCKING=1,用于把异步收集点的报错误导到真正的同步调用位置(该设置不解决崩溃)。
  • 关注 CUDA graphs 是否启用(报告者环境中已启用),以及 HiSparse 是否在 CUDAGraphMode.FULL 下运行。
  • 如果使用无 NIXL 的 colocated P/D + OffloadingConnector,该场景属于相似报错但根因未确认,需要单独排查。

解决步骤

  1. 先按 Issue 的最小复现条件核对你的部署:NIXL P/D、decode 端 HiSparse、block size 64、长输出 ramp 流量。如果这些条件不齐,崩溃可能来自其他路径。
  2. 在 decode engine 加 CUDA_LAUNCH_BLOCKING=1 重跑,观察报错是否从 _finish_mirror_phase → event.synchronize() 转移到 run_fullgraph → graphs[desc].replay()。若转移,说明 fault 发生在被 replay 的 graph 内部,而不是 mirror 同步点。
  3. 对照 vllm/v1/hisparse/runtime.py 中 finish_kv_update 附近对 CUDAGraphMode.FULL 的分支,确认你的版本是否会在 FULL replay 下跳过 submit_layer_mirror();这是 Issue 中指向 #56158 的具体代码位置。
  4. 可优先尝试评估 #56158 是否已经合并或能否应用。Issue 作者明确表示“尚未测试该 patch 是否消除崩溃”,所以这只是待验证方向,不是确认修复。
  5. 如果走的是 host import 路径,收集崩溃时的请求状态(running 请求数、context 长度、kv_cache_usage、是否有 preemption、每个请求的 SparseKVRowMirror 行数)。Issue 中崩溃时 kv_cache_usage=0.032、无 preemption,说明不是 GPU KV 耗尽也不是大 batch 导致。
  6. 若你的部署不使用 NIXL(例如单节点 colocated P/D + OffloadingConnector),先用一个更小的可复现开关定位差异,再判断是否与 host pool 注册相关;同时注意 Issue 已撤回 host 注册线索,不要直接照搬该方向。
  7. 如果升级到 TOT 后已无法复现,按 Issue 结尾说明处理:原作者以无法复现关闭,但若仍在 TOT 上复现可重新打开并附上最新最小复现。

验证方法

按 Issue 的 ramp(并发 1/2/4/8/16,ISL 32000 / OSL 2000,共约 72 个请求)跑满,确认在 C16 阶段不再出现 torch.AcceleratorError: CUDA error: unspecified launch failure,所有 TP worker 不再于同一步骤失败,且引擎在整轮请求中保持可服务、没有出现后续请求全部失败的情况。Issue 的基线数据显示崩溃时 C16 为 10 done / 22 fail,修复后该行应保持 done 递增且 fail 为 0。由于原作者无法复现,验证时应记录完整版本号、PR/commit、部署配置和完整日志,以便必要时重新打开 Issue。

参考来源

vllm-project/vllm #56699

GamsGo AI

AI 工具推荐

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

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

了解 GamsGo AI

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

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 27593

发表回复

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