Prhub

#26980 [fix] Skip routed expert capture for draft model under spec v2

原始 PR 作者 guapisolo 合并时间 2026-06-25 07:56 文件变更 5 提交数 10 评论 5 代码增减 +67 / -14

执行摘要

修复 draft 模型污染 target 路由专家捕获

症状:启用 --enable-return-routed-experts 且 MoE draft 模型时,返回的 routed_experts 与仅 target 的基准不一致。根因:RoutedExpertsCapturer 是进程全局单例,draft 与 target 共享同一缓冲区,draft 的 MoE TopK 会写入 target 的捕获缓冲区。PR 描述中明确提出需要保护 target 的捕获不受 draft 影响。

对于涉及 speculative decoding 或 MoE draft 模型的开发者,建议仔细阅读此 PR 的设计:如何通过配置标志实现跨后端的统一捕获门控,以及在初始化早期阻断副作用的时机选择。对于使用者,应升级以修复相关 bug。建议未来补充自动化测试以确保回归覆盖。

讨论亮点

Review 评论为空,PR 作者在描述中提出了三个审查焦点:确认 capture_routed_experts_if_allowed 是唯一捕获站点、检查 BYPASS 路径中标志的正确传递、确保 disable_routed_experts_capture_for_draft 在 graph/backend 初始化前运行。未产生实质性讨论。

实现拆解

  1. 添加配置标志:在 TopKConfig 中新增 allow_routed_experts_capture 字段(默认 True),用于标识该 TopK 是否允许触发路由专家捕获。
  2. 提取统一捕获入口:在 layers/moe/topk.py 中新增 capture_routed_experts_if_allowed 函数,将所有后端(CUDA _post_process_topk_ids、NPU fused_topk_npu)的直接捕获调用替换为该函数,确保捕获行为受标志控制。
  3. 新建 draft 阻断函数:在 state_capturer/routed_experts.py 中新增 disable_routed_experts_capture_for_draft,遍历模型模块将每个 TopK 实例的 allow_routed_experts_capture 设为 False。
  4. 集成到 ModelRunner:在 ModelRunner.initialize 中,对 draft worker 在 backend/graph 初始化之前调用 disable_routed_experts_capture_for_draft,同时修改 init_routed_experts_capturerforward 中的判断,确保 draft worker 跳过捕获器的初始化和 on_forward_end 调用。
  5. 适配 BYPASS 路径:在 fused_moe_triton/layer.py 的 BYPASS 路径中,将 allow_routed_experts_capture 标志通过函数参数传递,确保重建的 TopKConfig 保留正确的捕获状态。
文件 模块 状态 重要度
python/sglang/srt/layers/moe/topk.py MoE 路由 modified 6.95
python/sglang/srt/state_capturer/routed_experts.py 专家捕获 modified 6.79
python/sglang/srt/model_executor/model_runner.py 模型执行 modified 6.13
python/sglang/srt/hardware_backend/npu/moe/topk.py NPU 路由 modified 5.76
python/sglang/srt/layers/moe/fused_moe_triton/layer.py 融合 MoE modified 4.99

关键符号

capture_routed_experts_if_allowed disable_routed_experts_capture_for_draft

关键源码片段

python/sglang/srt/layers/moe/topk.py core-logic

核心修改:新增 TopKConfig.allow_routed_experts_capture 标志和统一的捕获入口函数 capture_routed_experts_if_allowed,所有后端通过此函数进行捕获,实现标志门控。

@dataclass
class TopKConfig:
    top_k: int
    # ... 其他已有字段 ...
    # Draft-side MoE blocks set this False so they never write the target's
    # process-global routed-experts capture buffer.
    allow_routed_experts_capture: bool = True
​
​
def capture_routed_experts_if_allowed(
    topk_config: TopKConfig,
    layer_id: Optional[int],
    topk_ids: torch.Tensor,
) -> None:
    """所有后端的单一捕获入口,受到每个配置的退出选项控制。"""
    if not topk_config.allow_routed_experts_capture:
        return
    if (cap := get_global_experts_capturer()) is not None:
        cap.capture(layer_id=layer_id, topk_indices=topk_ids)

评论区精华

确认捕获入口的唯一性 设计

PR 作者要求审查者确保 capture_routed_experts_if_allowed 是唯一的捕获站点,避免直接 capturer 写入绕过标志。

结论:代码中已将所有后端的捕获调用替换为该函数,保证唯一入口。 · 已解决

风险与影响

主要风险在于新增的 allow_routed_experts_capture 标志可能被某些后端或自定义 TopK 实现绕过,例如若存在直接调用全局捕获器 cap.capture() 的路径未迁移到统一入口,则标志无效。BYPASS 路径需确保 allow_routed_experts_capture 正确传递,否则可能导致行为不一致。另外,测试文件在最终 commit 中被移除(commit 4bec9f7),缺少自动化回归覆盖,潜在回归需依赖手动测试或后续补加测试。

影响用户:修复了使用 MoE draft 模型(如 DeepSeek-V3 MTP、Qwen3-MoE EAGLE3)且启用 --enable-return-routed-experts 时路由专家返回不准确的 bug。影响系统:添加了轻量布尔判断和一次模型遍历,性能影响可忽略。影响团队:为未来类似跨模型副作用阻断提供了可复用的模式(配置标志 + 统一入口 + 初始化早期阻断)。

测试已移除 BYPASS 路径易出错 跨后端一致性

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论