Prhub

#30139 [Fix] Skip cross-node probe in MultimemAllGatherer on single-node runs (fixes mooncake EP segfault)

原始 PR 作者 ch-wan 合并时间 2026-07-05 06:36 文件变更 1 提交数 1 评论 8 代码增减 +11 / -2

执行摘要

跳过单节点跨节点探针,修复 EP 段错误

CI 中 test_mooncake_ep_small.py 在启动时 segfault,根因是 PR #29881 在 MultimemAllGatherer 构造时添加的 gloo all-reduce 探针在单节点 mooncake EP 配置下崩溃。本 PR 旨在避免此探针在不必要且不安全的单节点场景下运行,以恢复 CI 通过性。

值得合并,修复了关键路径上的段错误。设计谨慎,采纳了 review 建议避免了遗留 accessor 增加和潜在的错误路径。建议阅读 MultimemAllGatherer.init 的修改,可作为在分布式组件中安全添加条件探测的范例。

讨论亮点

Review 中两条来自 chatgpt-codex-connector[bot] 的意见均被作者采纳:

  • 避免新增 legacy server-args accessor:bot 指出使用 get_global_server_args() 会增加遗留访问器计数(从 346 到 347),应改为 get_server_args()。作者最终使用 get_server_args()。
  • 避免 TP=1 时要求 server args:bot 指出在 TP=1 且 ServerArgs 尚未发布时,get_server_args() 会 raise ValueError。作者在条件中先检查 world_size > 1,确保不会在 TP=1 路径下调用 get_server_args()。

实现拆解

实现过程分为以下步骤:

  1. 导入 get_server_args 函数:在 MultimemAllGatherer.init 的惰性导入区域增加 from sglang.srt.runtime_context import get_server_args,提供读取部署节点数的能力。
  2. 增加 nnodes 条件判断:在原有 world_size > 1 条件基础上,增加 get_server_args().nnodes > 1,确保只有跨节点部署时才执行 in_the_same_node_as 探针。单节点时跳过探针,保持 multimem 启用(与 PR #29881 之前的行为一致)。
  3. 短路保护:先检查 world_size > 1,如果 TP 组大小为 1(如单 GPU 场景),则不触发 get_server_args() 调用,避免在 server args 尚未发布时引发 ValueError。
  4. 配套调整:仅修改了一个文件,无新增测试。CI 通过 4-GPU 测试 job 验证修复有效。
文件 模块 状态 重要度
python/sglang/srt/distributed/device_communicators/triton_symm_mem_ag.py 通信模块 modified 5.99

关键符号

MultimemAllGatherer.__init__

关键源码片段

python/sglang/srt/distributed/device_communicators/triton_symm_mem_ag.py dependency-wiring

唯一修改文件;在 MultimemAllGatherer.__init__ 中增加 nnodes > 1 条件判断以跳过跨节点探针,避免单节点 EP 部署下的 segfault。

# python/sglang/srt/distributed/device_communicators/triton_symm_mem_ag.pyclass MultimemAllGatherer:
    def __init__(
        self,
        max_tokens: int,
        *,
        enabled: bool = True,
        skip_entry_sync: bool = False,
    ):
        self._max_tokens = int(max_tokens)
        self._skip_entry_sync = skip_entry_sync
        # None 表示始终回退到 NCCL;_UNINIT 表示首次 eager 调用时构建
        self._state = self._UNINIT if enabled else None
        if self._state is self._UNINIT:
            from sglang.srt.distributed import get_tp_group
            from sglang.srt.distributed.parallel_state import in_the_same_node_as
            from sglang.srt.runtime_context import get_server_args
​
            tp_group = get_tp_group()
            # 仅在真正可能跨节点时探测拓扑,避免在单节点下执行
            # in_the_same_node_as() 中的 gloo all-reduce(在部分 EP 配置下会 segfault)
            if (
                tp_group.world_size > 1
                and get_server_args().nnodes > 1
                and not all(in_the_same_node_as(tp_group.cpu_group, source_rank=0))
            ):
                logger.warning(
                    "multimem all-gather disabled because the TP group spans "
                    "across nodes."
                )
                self._state = None

评论区精华

避免新增 legacy server-args accessor 设计

chatgpt-codex-connector[bot] 指出使用 get_global_server_args() 会增加遗留访问器计数,应使用 sglang.srt.runtime_context.get_server_args()。

结论:作者采纳建议,最终代码使用 get_server_args()。 · 已解决

避免 TP=1 时要求 server args 正确性

chatgpt-codex-connector[bot] 指出当 TP=1 且 ServerArgs 尚未发布时,get_server_args() 会 raise ValueError。建议先检查 world_size。

结论:作者在条件中先检查 tp_group.world_size > 1,确保不会在 TP=1 时调用 get_server_args()。 · 已解决

风险与影响

风险较低:

  • 场景遗漏:若用户配置了 nnodes=2 但实际只使用单节点,探针仍会执行,可能触发 segfault。但这种情况在实践中罕见,且 nnodes 通常由启动脚本正确设置。
  • 倒退风险:单节点下 multimem 保持启用,与 PR #29881 之前的旧行为一致,无功能退化。
  • 依赖风险:get_server_args() 在 server args 已发布前被调用可能导致错误。但代码通过先检查 world_size > 1 避免了此路径,仅当 world_size > 1 时才读取 server args,此时 server args 应已发布。

直接影响:修复单节点 mooncake EP 配置下的服务器启动 segfault,使 test_mooncake_ep_small.py CI 测试通过。对多节点部署无影响(保留探针)。对用户透明的 bugfix,不改变外部 API 或性能特征。团队 CI 恢复正常。

段错误修复 单节点特定 探针绕过 边界条件处理

关联 Issue

#29881 Avoid logits multimem all-gather on cross-node TP groups
#30079 [MoE] Fix moe_fused_gate out-of-range expert id on all-NaN rows (fixes eagle_dp_attention crash)

完整报告

参与讨论