Prhub

#29881 Avoid logits multimem all-gather on cross-node TP groups

原始 PR 作者 san-tian 合并时间 2026-07-04 15:24 文件变更 1 提交数 2 评论 9 代码增减 +14 / -0

执行摘要

禁用跨节点 TP 的 logits multimem all-gather

在 4 节点 H20 部署(TP16/TP32)中,启动时 CUDA graph 捕获阶段尝试跨节点创建对称内存,但 torch.distributed._symmetric_memory.rendezvous 失败,导致服务无法就绪。PR body 明确描述该路径在跨节点场景下不可用,需与其他跨节点禁用策略保持一致。

该 PR 修复了多节点 TP 部署的阻塞性问题,代码简洁,审查充分,建议快速合入。无需精读,但设计模式(在构造函数中禁用跨节点路径)值得在类似场景中复用。

讨论亮点
  1. 检查位置争议:mmangkad 最初建议将检查移至 _build() 方法中,以守卫真正的 rendezvous 组而非构造函数时的组。但 Fridge003 指出 rendezvous 组与构造函数时的组相同,放在 __init__ 中即可。最终采用 __init__ 方案。
  2. 测试文件移除:Fridge003 认为无需新增单独测试文件,san-tian 移除了测试。

实现拆解

  1. MultimemAllGatherer.__init__ 中增加跨节点检测
    使用 get_tp_group() 获取 TP 组,通过 in_the_same_node_as(tp_group.cpu_group, source_rank=0) 检查所有 rank 是否在同一节点。若 world_size > 1 且不全在同一节点,则将 self._state 设为 None,从而禁用 multimem 快速路径。该检查仅在 enabled=True_state_UNINIT)时执行,避免重复导入。

  2. 回退机制__call__ 中当 _stateNone 时,直接调用 tensor_model_parallel_all_gather(NCCL 回退),保持原有逻辑不变。

  3. 依赖管理:延迟导入 get_tp_groupin_the_same_node_as,避免模块加载时的循环依赖。
文件 模块 状态 重要度
python/sglang/srt/distributed/device_communicators/triton_symm_mem_ag.py 分布式通信 modified 6.47

关键符号

MultimemAllGatherer.__init__ in_the_same_node_as

关键源码片段

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

核心变更文件,在 `MultimemAllGatherer` 初始化时增加跨节点 TP 检测逻辑,决定是否禁用 multimem all-gather 快速路径。

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 => always NCCL; _UNINIT => build on first eager call.
    self._state = self._UNINIT if enabled else None
    # 新增:如果 TP 组跨节点,则立即禁用 multimem all-gather
    # 从而避免启动时 rendezvous 失败导致的挂起
    if self._state is self._UNINIT:
        # Lazy import avoids a module-load dependency on the distributed facade.
        from sglang.srt.distributed import get_tp_group
        from sglang.srt.distributed.parallel_state import in_the_same_node_as
​
        tp_group = get_tp_group()
        if tp_group.world_size > 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 # 禁用快速路径,__call__ 将走 NCCL fallback

评论区精华

检查位置应放在 `_build()` 还是 `__init__()` 设计

mmangkad 建议将跨节点检查移至 `_build()` 以守卫真正的 rendezvous 组;Fridge003 认为 rendezvous 组与构造函数时的组相同,放在 `__init__` 即可。

结论:采用 `__init__` 方案,因为两者组一致且实现更简洁。 · 已解决

是否新增测试文件 测试

Fridge003 认为无需新增测试,san-tian 随后移除了测试文件。

结论:不新增测试,仅修改源码。 · 已解决

风险与影响

风险较低。仅当 TP 组跨节点且 multimem all-gather 被启用时才生效,且回退到已广泛使用的 NCCL all-gather 路径。若有单节点跨节点配置混合的情况(罕见),可能无法正确检测,但影响仅为无法享受 multimem 加速。

影响范围有限,仅涉及跨节点 TP 组部署场景(如 TP16 跨 2 节点、TP32 跨 4 节点)。修复后服务可正常启动,无性能回归。单节点 TP 组不受影响。

核心路径变更 缺少测试覆盖 跨节点部署

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论