Prhub

#25083 fix(mooncake): honour MOONCAKE_PROTOCOL so EFA hardware can select efa transport

原始 PR 作者 whn09 合并时间 2026-05-29 14:21 文件变更 3 提交数 7 评论 18 代码增减 +18 / -18

执行摘要

Mooncake 传输引擎支持环境变量选择 EFA 协议

在AWS EFA实例(如p5en.48xlarge)上运行SGLang时,使用--disaggregation-transfer-backend mooncake会在首次KV缓存传输时崩溃,错误为"Failed to create QP: Operation not supported [95]"。根本原因是两个调用点硬编码了"rdma"协议,而EFA硬件需要"efa"协议(使用libfabric SRD,而非ibverbs RC QP)。详情见关联Issue #24838。

建议精读本PR的代码改动,重点关注"如何通过单一环境变量统一两个调用点的协议配置"以及"重构后分支合并的代码组织"。对于部署在AWS EFA的用户,该PR是必合的。

讨论亮点
  1. 使用环境变量管理方案:gemini-code-assist[bot]建议使用集中的envs对象而非直接访问os.environ。作者回复称已采纳,并改用envs.MOONCAKE_PROTOCOL.get(),同时通过is_set()守卫保留旧行为。

  2. 默认值争议:ShangmingCai指出需要将默认值改为"rdma"而非"tcp",以避免现有IB/RoCE用户意外降级。作者最终在后续commit中将environ.py中的默认值改为"rdma",并移除了is_set()守卫。

  3. 逻辑分支合并建议:stmatengss建议合并Ascend和通用分支的初始化逻辑,使代码更简洁。作者重构后使用单一protocol变量,统一调用engine.initialize

  4. Lint修复与CI重跑:ShangmingCai要求修复lint,并多次使用/rerun-failed-ci命令重跑失败的CI(最终多为infra问题)。

实现拆解

  1. 修改默认协议:在python/sglang/srt/environ.py中,将MOONCAKE_PROTOCOL的默认值从"tcp"改为"rdma",使所有消费者(包括Mooncake Store和传输引擎)默认使用rdma协议,保持向后兼容。

  2. 重构传输引擎初始化:在python/sglang/srt/distributed/device_communicators/mooncake_transfer_engine.pyinitialize方法中,移除了硬编码的"rdma"分支,改用envs.MOONCAKE_PROTOCOL.get()读取协议字符串;同时将Ascend和非Ascend路径合并为一条engine.initialize调用,提高了代码可维护性。

  3. 适配模型运行器:在python/sglang/srt/model_executor/model_runner.pyremote_instance_init_transfer_engine方法中,同样将硬编码的"rdma"替换为envs.MOONCAKE_PROTOCOL.get(),确保远程实例传输引擎也能响应环境变量。

该变更不涉及测试文件,因为端到端EFA测试需要特殊硬件和编译环境。环境变量MOONCAKE_PROTOCOL已在Mooncake Store的README中。

文件 模块 状态 重要度
python/sglang/srt/distributed/device_communicators/mooncake_transfer_engine.py 传输引擎 modified 6.76
python/sglang/srt/model_executor/model_runner.py 模型运行 modified 5.17
python/sglang/srt/environ.py 环境配置 modified 4.89

关键符号

MooncakeTransferEngine.initialize ModelRunner.remote_instance_init_transfer_engine MOONCAKE_PROTOCOL

关键源码片段

python/sglang/srt/distributed/device_communicators/mooncake_transfer_engine.py core-logic

核心修改:移除硬编码 rdma,改用 envs.MOONCAKE_PROTOCOL 读取协议,并重构 Ascend 分支逻辑,使通过单一初始化路径运行。

def initialize(
    self,
    hostname: str,
    device_name: Optional[str],
) -> None:
    """Initialize the mooncake instance."""
    # 当启用了 Ascend 传输时,使用 "ascend" 协议
    if envs.ENABLE_ASCEND_TRANSFER_WITH_MOONCAKE.get():
        npu_phy_id = envs.ASCEND_NPU_PHY_ID.get()
        suffix = self.gpu_id if npu_phy_id == -1 else npu_phy_id
        hostname += f":{get_free_port()}:npu_{suffix}"
        protocol = "ascend"
    else:
        # MOONCAKE_PROTOCOL 选择传输层协议:rdma | efa | tcp | ...
        # 默认是 "rdma";在 AWS EFA 上要设置 MOONCAKE_PROTOCOL=efa
        protocol = envs.MOONCAKE_PROTOCOL.get()
​
    # 将 protocol 传递给 Mooncake TransferEngine
    ret_value = self.engine.initialize(
        hostname,
        "P2PHANDSHAKE",
        protocol,
        device_name if device_name is not None else "",
    )
    if ret_value != 0:
        logger.error("Mooncake Transfer Engine initialization failed.")
        raise RuntimeError("Mooncake Transfer Engine initialization failed.")
python/sglang/srt/model_executor/model_runner.py core-logic

第二个调用点,同样使用 envs.MOONCAKE_PROTOCOL 替换硬编码 rdma,确保远程实例传输引擎初始化一致。

def remote_instance_init_transfer_engine(self):
    try:
        from mooncake.engine import TransferEngine
    except ImportError as e:
        logger.warning(
            "Please install mooncake for using remote instance transfer engine: pip install mooncake"
        )
        return
    self.remote_instance_transfer_engine = TransferEngine()
    local_ip = get_local_ip_auto()
    # 使用 envs.MOONCAKE_PROTOCOL.get() 获取协议(默认 "rdma"),
    # 用户可通过环境变量覆盖(例如 export MOONCAKE_PROTOCOL=efa)
    self.remote_instance_transfer_engine.initialize(
        local_ip,
        "P2PHANDSHAKE",
        envs.MOONCAKE_PROTOCOL.get(),
        envs.MOONCAKE_DEVICE.get(),
    )
    self.remote_instance_transfer_engine_session_id = NetworkAddress(
        local_ip, self.remote_instance_transfer_engine.get_rpc_port()
    ).to_host_port_str()

评论区精华

环境变量访问方式 设计

gemini-code-assist[bot] 建议使用中央化的 envs 对象而非直接 os.environ,以保持一致性。

结论:作者接受建议,改用 envs.MOONCAKE_PROTOCOL.get(),并添加 is_set() 守卫保留旧行为。 · 已解决

合并逻辑分支 style

stmatengss 建议合并 Ascend 和通用分支的初始化逻辑,避免重复代码。

结论:作者重构 initialize 方法,使用单一 protocol 变量,所有分支共用同一个 engine.initialize 调用。 · 已解决

默认值变更 正确性

ShangmingCai 指出需要将 MOONCAKE_PROTOCOL 默认值从 "tcp" 改为 "rdma",以保持与历史行为一致。

结论:作者将 environ.py 中的默认值改为 "rdma",并移除了 is_set() 守卫。 · 已解决

风险与影响

  1. 回归风险:现有InfiniBand/RoCE用户若不设置MOONCAKE_PROTOCOL,默认仍为"rdma",与之前行为一致;Mooncake Store用户之前依赖默认"tcp",但Store有自己的初始化逻辑,且团队已确认该默认值变更对Store无影响。

  2. 兼容性风险:用户需使用编译了USE_EFA=ON的Mooncake wheel才能使用"efa"协议,否则初始化仍会失败。

  3. 缺少测试覆盖:没有对应的端到端测试,因为需要EFA硬件和定制编译。CI中仅依赖基础单元测试,可能遗漏回归。

用户影响:AWS EFA用户现在可以通过设置MOONCAKE_PROTOCOL=efa来启用EFA传输,消除KV缓存传输崩溃。现有IB/RoCE用户无感知。

系统影响:变更限于初始化阶段,无运行时性能影响。

团队影响:低维护成本,环境变量方案统一了协议配置方式。

默认值变更影响 Mooncake Store 使用者 需要 Mooncake 编译支持 EFA 缺少端到端测试覆盖

关联 Issue

#2070 [Bug] efa_transport not used during KV transfer on AWS EFA: rdma_transport instantiated again in batch_transfer_sync
#24838 [Bug] Mooncake transfer backend crashes on AWS EFA: hardcoded `rdma` protocol bypasses `efa_transport`

完整报告

参与讨论