[deepseek-v4-flash-sm86 fork] PP8 + DSpark: recurring deadlock in the V2-runner PP sampled-token/draft broadcast protocol (PPHandler)

该报错发生在 vLLM V2 Runner 启用流水线并行(PP=8)配合 DSpark 投机解码(DeepSeek-V4-Flash 模型)时,表现为长时间运行后 PP 末级 rank 死锁、采样 token 广播协议错位。优先排查 PP 广播的 NCCL 集体通信调度是否因数据依赖产生跨步错位,

快速结论:该报错发生在 vLLM V2 Runner 启用流水线并行(PP=8)配合 DSpark 投机解码(DeepSeek-V4-Flash 模型)时,表现为长时间运行后 PP 末级 rank 死锁、采样 token 广播协议错位。优先排查 PP 广播的 NCCL 集体通信调度是否因数据依赖产生跨步错位,并检查异步调度下 in-flight batch 数量是否超过 pp_size。

适用环境:vLLM 0.11.2.dev278 基础版(LimeChain/vllm 的 deepseek-v4-flash-sm86 分支,commit ccfeb3a8),DeepSeek-V4-Flash-0731 模型(内置 DSpark drafter),8× RTX 3090(仅 PCIe,无 P2P/NVLink),Ubuntu 24.04,驱动 595.84,`VLLM_USE_V2_MODEL_RUNNER=1`。

最快修复方案:暂无针对上游 vLLM 的已验证一步修复方案。在 LimeChain SM86 分支中,通过 PR LimeChain/vllm#1 修复:将 PP sampled-token 广播改为固定 4 次广播调度,并在接收端校验 seq/mask/num_reqs 头;同时将异步调度的 in-flight batches 上限从 pp_size+1 降为 pp_size(可选开启)。

注意事项:上述修复只在 LimeChain 分支中验证,尚未合入上游 vLLM;`max_concurrent_batches` 限制为 pp_size 可能影响吞吐,但官方未提供量化对比数据。

问题场景

用户在 vLLM V2 Runner(`VLLM_USE_V2_MODEL_RUNNER=1`)下,以 PP=8、TP=1 加载 DeepSeek-V4-Flash-0731 并启用 DSpark 投机解码。在长时间 agentic 流量(上下文约 190K–230K tokens,前缀缓存命中率约 94%)下,运行几分钟到几十分钟后发生死锁:GPU 0–6 占用率 100% 空转,GPU 7(PP7,末级)占用率 0%,生成 token 计数冻结,随后报 sample_tokens 超时并触发 EngineDeadError,SIGTERM 无法正常退出。

报错原文

[PG ID 8 PG GUID 85(pp_broadcast) Rank R] failure detected by watchdog at work sequence id: 40427
  PG status: last enqueued work: 40432, last started work: -1, last completed work: 40426
Watchdog caught collective operation timeout: WorkNCCL(SeqNum=40427, OpType=BROADCAST, NumelIn=6, Timeout(ms)=60000)

No available shared memory broadcast block found
TimeoutError: RPC call to sample_tokens timed out
EngineDeadError

原因分析

可能原因有两个独立缺陷叠加:

  • 广播协议跨步 FIFO 错位:PPHandler 的 sampled-token/draft 广播调度依赖数据(mask 是否非 None)做发送/跳过门控,且无 rendezvous 校验。非末级 rank 每步按自身 compute_need_sampled_mask() 发布 3 次 NCCL 广播 recv,末级 rank 则按自身 mask 发送 2 次广播,第三个 draft 广播在 speculator.propose() 成功后才单独发送。接收端通过 FIFO 延迟 8 步(pp_size)消费,一次错位会污染 8 步后的主数据流。NCCL watchdog 反复捕获到 NumelIn=6 的广播,与协议实际载荷形状([12,i64][2,12,i32][12,5,i64])均不匹配,符合跨步 FIFO 错位特征。
  • 异步调度 concurrency 越界:异步调度下 max_concurrent_batches=pp_size+1 允许一个 in-flight 的 sample_tokens 比末级 PP rank 领先一步。NCCL flight-recorder 转储显示接收端已入队 draft-broadcast seq N+1,而末级 rank 仍在处理 N,导致接收端集体操作整体前移一个序号。

环境排查

  • 确认运行分支为 LimeChain/vllm deepseek-v4-flash-sm86,commit ccfeb3a8baac21d7e1364c609dfa88f2e0230cfd,vLLM 基础版本 0.11.2.dev278。
  • 确认 VLLM_USE_V2_MODEL_RUNNER=1 已设置。
  • 核对启动参数:--pipeline-parallel-size 8 --tensor-parallel-size 1 --distributed-executor-backend mp --speculative-config '{"method":"dspark","num_speculative_tokens":5}'
  • 确认 NCCL 是否启用 60 秒 watchdog 超时以便捕获死锁现场。
  • 检查是否有 P2P/NVLink(本 Issue 环境为 PCIe only,可能加剧广播延迟抖动)。

解决步骤

  1. 若使用 LimeChain SM86 分支,拉取并应用 LimeChain/vllm#1 的修复,其中包含两处改动:将 PP sampled-token 广播改为固定 4 次广播调度,并在接收端校验 int64 seq/mask/num_reqs 头,杜绝数据依赖导致的门控跳过。
  2. 如修复仍未覆盖,可优先尝试将异步调度的 in-flight 批次上限从 pp_size+1 下调为 pp_size(该分支为 opt-in 选项),消除 in-flight sample_tokens 比末级 rank 领先一步的竞态。
  3. 若无法使用修复分支,可考虑关闭 DSpark 投机解码(去掉 --speculative-config)作为临时规避手段,但 Issue 中未验证此方案。
  4. 死锁发生后不要只依赖 SIGTERM,需对 vllm 进程执行 kill -9 清理 NCCL 组。

验证方法

以相同配置重启服务,在类似工作负载下持续运行至少 66 分钟(Issue 中验证时长),确认无 TimeoutError: RPC call to sample_tokens timed out、无 No available shared memory broadcast block found 日志,生成 token 计数器不冻结,GPU 7 不落入 0% 占用率。可进一步检查 NCCL flight-recorder 确认广播序列号连续无跨步。

参考来源

vllm-project/vllm #53402

GamsGo AI

AI 工具推荐

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

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

了解 GamsGo AI

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

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 19765

发表回复

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