Prhub

#23423 [NPU] Fix mrope_position computation in Eagle Worker v2 with PlanStream

原始 PR 作者 silencejade 合并时间 2026-05-11 09:43 文件变更 3 提交数 6 评论 13 代码增减 +22 / -2

执行摘要

修复 NPU 推测解码中 mrope_position 竞态条件

PR body 说明:'When SGLANG_ENABLE_SPEC_V2 and SGLANG_ENABLE_OVERLAP_PLAN_STREAM are enabled in multimodal scenarios, the Eagle Worker v2 computes mrope_position on the plan stream using draft outputs from the default stream. This race condition leads to incorrect mrope_position values.'

值得精读。展示了异步流竞态修复的典型模式:在等待流同步后重新计算依赖值,并正确同步到 CUDA graph buffer。对理解 speculative decoding 中的流管理和 CUDA graph 缓冲有参考价值。

讨论亮点
  • Todobe:建议将 mrope_position 重计算代码放在 wait_stream 之后以防止流冲突。(✅ 已修复)
  • Todobe:建议先判断 _is_npu 以优化性能。(✅ 已调整顺序)
  • Hexq0210:询问为什么将私有方法改为公有方法。silencejade 回复:因为需要作为公有函数在外部调用。

实现拆解

  1. 方法公有化:在 forward_batch_info.py 中将私有方法 _compute_spec_mrope_positions 重命名为公有方法 compute_spec_mrope_positions,使其可以被外部模块调用。

  2. 核心修复:在 eagle_worker_v2.pyverify 方法中,等待 plan stream 完成后,检测 NPU 后端、mrope 模型等条件,如果满足则调用 compute_spec_mrope_positions 重新计算正确的 mrope_position,覆盖 plan stream 中因竞态产生的错误值。

  3. Graph buffer 同步:在 npu_graph_runner.pyreplay 方法中,当启用 SGLANG_ENABLE_OVERLAP_PLAN_STREAMforward_batch.mrope_positions 不为 None 时,将其拷贝到 self.buffers.mrope_positions,确保 CUDA graph 使用正确的 mrope_position。

文件 模块 状态 重要度
python/sglang/srt/model_executor/forward_batch_info.py 前向批信息 modified 5.32
python/sglang/srt/hardware_backend/npu/graph_runner/npu_graph_runner.py NPU 图执行器 modified 5.04
python/sglang/srt/speculative/eagle_worker_v2.py 推测解码 modified 5.4

关键符号

compute_spec_mrope_positions verify replay

关键源码片段

python/sglang/srt/speculative/eagle_worker_v2.py core-logic

核心修复逻辑:在 verify 中等待 plan stream 后重新计算 mrope_position,覆盖错误值。

# eagle_worker_v2.py verify 方法片段
# 等待 plan stream 完成同步
if self.plan_stream:
    torch.get_device_module(self.device).current_stream().wait_stream(
        self.plan_stream
    )
    # 修复:在 NPU + mrope + spec_info 非 idle 时,重新计算 mrope_position
    # 因为 plan stream 使用的 draft outputs 可能来自 default stream,
    # 导致竞态错误,此处确保在 default stream 上正确计算。
    if (
        _is_npu
        and self._target_worker.model_runner.model_is_mrope
        and batch.spec_info is not None
        and getattr(batch.spec_info, "positions", None) is not None
        and not batch.forward_mode.is_idle()
    ):
        verify_forward_batch.compute_spec_mrope_positions(
            self._target_worker.model_runner, batch
        )

评论区精华

代码放置位置 正确性

Todobe 建议将 mrope_position 重计算代码放在 wait self.plan_stream 之后以防止流冲突。

结论:silencejade 已修复,将代码放在 wait_stream 后。 · 已解决

条件判断顺序 性能

Todobe 建议先判断 _is_npu 以优化性能。

结论:silencejade 已调整顺序。 · 已解决

方法重命名 设计

Hexq0210 问为什么将私有方法改为公有方法。

结论:silencejade 解释因为需要作为公有函数在外部调用。 · 已解决

风险与影响

变更仅影响 NPU 后端且必须同时启用 SPEC_V2、OVERLAP_PLAN_STREAM 和多模态输入,影响面窄。但该方法调用通过条件判断动态执行,未来若有新增调用点需确保正确性。缺少明确的单元测试覆盖该竞态场景。

修复了特定配置下多模态推测解码的数值错误,用户无需修改配置即可获得正确结果。性能影响极小,仅增加一次同步后的额外计算和少量数据传输。

特定配置触发 缺少测试覆盖 NPU 后端路径

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论