Prhub

#29030 [NPU] use standalone group for moe ep

原始 PR 作者 iforgetmyname 合并时间 2026-07-10 08:49 文件变更 2 提交数 3 评论 3 代码增减 +18 / -6

执行摘要

NPU 使用独立 EP 通信组

NPU 硬件上需要独立的 EP 通信组,否则在长输入场景下会触发 dispatch 函数崩溃(见 Issue 评论中 Yuxin1999 的反馈)。

值得合并。PR 聚焦、改动小、解决真实崩溃问题,且得到 reviewers 确认。建议后续补充 NPU 相关的单元测试。

讨论亮点

无实质性 review 讨论。whybeyoung 批准 PR,Yuxin1999 在 Issue 中反馈该 PR 修复了 910B3 上长输入 dispatch 崩溃。

实现拆解

  1. 导入依赖与检测 NPU:在 layer.py 中导入 get_moe_ep_groupis_npu,新增模块级变量 _is_npu = is_npu()
  2. 新增通信组选择函数 _get_deepep_comm_group:接收 a2a_backend 参数,默认返回 get_tp_group().device_group;若为 MORI 后端则返回 get_tp_group()(对象而非 device_group);若为 NPU 则返回 get_moe_ep_group().device_group
  3. 更新 dispatcher 创建逻辑create_moe_dispatcher 中构建 MaybeTboDeepEPDispatcher 时,将内联的通信组选择替换为调用 _get_deepep_comm_group(a2a_backend)
  4. 修改 EP 组初始化条件:在 parallel_state.py 中,将 _MOE_EP = _TP 的条件从 moe_ep_size == tensor_model_parallel_size 改为 moe_ep_size == tensor_model_parallel_size and not _is_npu,使 NPU 始终走 else 分支创建独立 EP 组。
文件 模块 状态 重要度
python/sglang/srt/layers/moe/fused_moe_triton/layer.py MoE 层 modified 6.83
python/sglang/srt/distributed/parallel_state.py 分布式 modified 4.99

关键符号

_get_deepep_comm_group

关键源码片段

python/sglang/srt/layers/moe/fused_moe_triton/layer.py core-logic

核心变更:新增 `_get_deepep_comm_group` 函数,根据硬件选择 EP 通信组;修改 dispatcher 创建逻辑。

# python/sglang/srt/layers/moe/fused_moe_triton/layer.pyfrom sglang.srt.distributed import (
    get_moe_ep_group, # 新增导入,用于 NPU 独立 EP 组
    get_tp_group,
    ...
)
from sglang.srt.utils import (
    is_npu, # 新增导入,检测 NPU 硬件
    ...
)_is_hip = is_hip()
_is_cpu_amx_available = cpu_has_amx_support()
_is_cpu = is_cpu()
_is_npu = is_npu() # 模块级标志,用于后续分支判断
_use_aiter = get_bool_env_var("SGLANG_USE_AITER") and _is_hip
​
​
def _get_deepep_comm_group(a2a_backend):
    # 默认使用 TP 组的 device_group
    group = get_tp_group().device_group
​
    if a2a_backend.is_mori():
        # MORI 后端需要 TP 组对象本身
        group = get_tp_group()
    elif _is_npu:
        # NPU 要求独立的 EP 通信组
        group = get_moe_ep_group().device_group
​
    return group
​
​
def create_moe_dispatcher(moe_runner_config: MoeRunnerConfig) -> BaseDispatcher:
    a2a_backend = get_moe_a2a_backend()
    ...
    elif ...:
        return MaybeTboDeepEPDispatcher(
            group=_get_deepep_comm_group(a2a_backend), # 原内联逻辑提取为函数调用
            ...
        )
python/sglang/srt/distributed/parallel_state.py core-logic

修改 EP 组初始化条件,使 NPU 上始终创建独立 EP 组而非复用 TP 组。

# python/sglang/srt/distributed/parallel_state.py
​
    global _MOE_EP
    assert _MOE_EP is None, "expert model parallel group is already initialized"
    # NPU 要求独立的 EP 组,即使 moe_ep_size 等于 tp_size
    if moe_ep_size == tensor_model_parallel_size and not _is_npu:
        _MOE_EP = _TP # 非 NPU 时复用 TP 组
    else:
        # NPU 或其他情况:创建独立 EP 组
        group_ranks = []
        ...
        _MOE_EP = init_model_parallel_group(
            group_ranks,
            ...
            group_name="moe_ep",
        )

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

风险较低:仅影响 NPU 硬件路径,且原有 TP 组复用逻辑在非 NPU 上保持不变。但未添加对应单元测试,回归依赖 CI。

影响 NPU 上的 MoE 模型推理,修复长输入场景下的崩溃问题。对其他硬件(CUDA、CPU 等)无影响。

缺少测试覆盖

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论