Prhub

#46116 [Core][KV-transfer] MoRIIO: heterogeneous TP<->DP prefill/decode read routing

原始 PR 作者 edwinlim0919 合并时间 2026-07-27 10:10 文件变更 3 提交数 9 评论 13 代码增减 +467 / -7

执行摘要

为 MoRIIO 添加异构 TP/DP 并行路由支持

参考 RFC #46107,当前 MoRIIO 假设预填充和解码引擎使用相同的并行度布局。然而,对于如 DeepSeek-R1 的工作负载,预填充受延迟限制最佳为 TP,解码受吞吐限制最佳为 DP/EP。异构并行能够在高并发下实现更高的吞吐量和更低的 TTFT。性能数据显示,在 512 并发请求时,2P_TP8:1D_DP8EP 配置相比同构 TP8 在吞吐量和 TTFT 上均有显著提升。

值得精读。该 PR 展示了在异构并行环境下如何优雅地解决 KV 传输路由问题,特别是死锁预防和负载均衡的设计。对于了解 MoRIIO 内部机制和分布式推断性能优化的开发者而言,其中的 _eager_handshake_all_dp_ranks_next_flex_tp_rank 实现具有较高学习价值。建议关注配套的 RFC #46107 和相关 PR #46115、#47495 以获取完整上下文。

讨论亮点

由于该 PR 的 review 评论为空,主要讨论发生在 PR 常规评论中。PR 作者 edwinlim0919 多次请求 review,并提供了在 MI300X 上使用 DeepSeek-R1 模型的端到端验证结果,包括准确率(gsm8k strict-match 0.9613)和吞吐量数据。reviewer tanpinsiang 在最后一个评论中提供了独立的测试验证,使用 MiniMax-M3-MXFP8 模型在 TP8 同构配置下进行回归测试,确认 73 个单元测试全部通过,且 router/prefill/decode 健康检查均正常。没有发现设计争议或未解决的问题。

实现拆解

该 PR 的实现分为三个主要步骤:

  1. 修复预填充 DP 排名硬编码:在 moriio_connector.py 中,修改 _resolve_read_source_moriio_handshake 函数,使其使用来自 proxy 传递的 remote_dp_rank 字段(存储于 ReqMeta.remote_dp_rank),而非始终使用 DP0。在 moriio_common.pyReqMeta 数据类中新增 remote_dp_rank: int = 0 字段,并在 add_new_req 中从 kv_transfer_params 解析该值。默认值为 0,保持与原有对称单 DP 行为的字节级兼容。

  2. 引入急切前向握手机制:新增 _eager_handshake_all_dp_ranks 方法,在每次解码前向传播开始时,对所有可能读取的远程预填充 DP 排名执行一次握手机制。所有本地 TP worker 通过 CPU all_reduce(MIN) 屏障同步,确保所有 worker 在进入前向步骤前完成握手,防止因懒惰握手机制导致部分 worker 进入前向集合操作而另一部分 worker 仍阻塞在握手 recv() 的死锁情况。使用 _eager_handshaked_engines 集合避免重复握手。

  3. 灵活的预填充 TP 读取(镜像配置):新增 _next_flex_tp_rank 方法,在 TP 预填充 + MLA + DP 解码(即镜像)配置下,解码 worker 可以轮询读取预填充 TP 0..N-1 中的任意一个,而非全部固定读取 TP0。该选择基于严格的确定性轮询算法,按解码 worker 的 DP 排名偏移,确保均匀的 NIC 负载分布。轮询行为仅在满足所有条件(world_size==1, use_mla, remote_dp_size==1, remote_tp_size>1)时启用,否则回退到原有固定映射。

配套测试:新增 tests/v1/kv_connector/unit/test_moriio_routing_fairness.py,轻量级(无需 GPU/ROCm/mori),直接驱动真实的 _resolve_read_source_next_flex_tp_rank 函数,覆盖 RFC 中所有同构和混合配置,验证硬件公平的预填充读取分布。

文件 模块 状态 重要度
vllm/distributed/kv_transfer/kv_connector/v1/moriio/moriio_connector.py 路由逻辑 modified 8.84
tests/v1/kv_connector/unit/test_moriio_routing_fairness.py 测试 added 7.99
vllm/distributed/kv_transfer/kv_connector/v1/moriio/moriio_common.py 数据模型 modified 5.13

关键符号

get_engine_name_with_dp_tp _eager_handshake_all_dp_ranks _next_flex_tp_rank _resolve_read_source

关键源码片段

tests/v1/kv_connector/unit/test_moriio_routing_fairness.py test-coverage

新增的轻量级测试文件,验证路由逻辑的公平性。通过构造 `MoRIIOConnectorWorker` 实例直接调用真实路由函数,覆盖 RFC 中的五种配置,确保对称 TP、灵活 TP、所有者 DP 三种行为均正确,并且轮询确定性、均匀性和交错性得到断言。

# 轻量级单元测试核心:构造虚拟 worker 并调用真实路由函数
# 模拟 proxy 的公平请求流,验证连接器不会引入瓶颈# PDConfig 数据类描述预填充 / 解码模式的维度
@dataclass(frozen=True)
class PDConfig:
    name: str
    p_mode: str # "TP8" 或 "DP8EP"
    d_mode: str
​
    @property
    def p_dp(self) -> int: # 预填充 DP 大小
        return MODE_DIMS[self.p_mode][0]
    @property
    def p_tp(self) -> int: # 预填充 TP 大小
        return MODE_DIMS[self.p_mode][1]
    @property
    def d_dp(self) -> int: # 解码 DP 大小
        return MODE_DIMS[self.d_mode][0]
    @property
    def d_tp(self) -> int: # 解码 TP 大小
        return MODE_DIMS[self.d_mode][1]
    @property
    def n_prefill_gpus(self) -> int:
        return self.p_dp * self.p_tp# 覆盖 RFC 中的五种 P/D 配置
CONFIGS = [
    PDConfig("1P_TP8:1D_TP8", "TP8", "TP8"),
    PDConfig("2P_TP8:1D_DP8EP", "TP8", "DP8EP"),
    PDConfig("2P_TP8:2D_TP8", "TP8", "TP8"),
    PDConfig("2P_DP8EP:3D_DP8EP", "DP8EP", "DP8EP"),
    PDConfig("2P_DP8EP:4D_TP8", "DP8EP", "TP8"),
]# 核心测试函数:根据配置生成公平请求流,收集每个预填充 GPU 的命中计数
def prefill_target_multiset(cfg: PDConfig, rounds: int) -> Counter:
    workers = build_decode_workers(cfg)
    hits: Counter = Counter()
    for _ in range(rounds):
        for owner_dp in range(cfg.p_dp): # 模拟 proxy 公平分配
            for worker in workers:
                meta = make_meta(
                    p_tp=cfg.p_tp, p_dp=cfg.p_dp, remote_dp_rank=owner_dp
                )
                chosen_tp, _flexible = worker._resolve_read_source(meta)
                # 计算对应的全局 GPU 索引
                hits[(owner_dp, chosen_tp)] += 1
    return hits

评论区精华

测试验证结果 测试

tanpinsiang 提供了独立的回归测试结果,使用 MiniMax-M3-MXFP8 模型验证 TP8 同构配置下所有单元测试通过,router/prefill/decode 健康正常。

结论:验证了异构路由逻辑在回归测试中无退化。 · 已解决

风险与影响

  1. 兼容性风险:新增的 remote_dp_rank 字段默认值为 0,且所有新逻辑由条件门控(flexible_gate),对称 TP 和所有者 DP 行为与之前字节级一致,无需担心回归。
  2. 死锁风险:急切握手机制使用了 CPU 同步屏障,若某个 worker 的握手失败(如网络分区),所有 worker 将统一失败快速,避免长时间挂起。但增加了前向传播前的延迟,不过由于握手仅执行一次,后续命中缓存,对持续运行的影响可忽略。
  3. 性能风险:轮询负载均衡引入了确定性计算开销,但相对于 RDMA 传输延迟极低。
  4. 测试覆盖:轻量级单元测试覆盖了所有路由逻辑,但缺乏集成测试验证实际硬件上的端到端行为(已在作者独立测试中覆盖)。

用户影响:对于使用 MoRIIO 进行 KV 传输并希望采用异构预填充/解码并行度的用户,该 PR 提供了关键支持,允许配置如 TP8 预填充 + DP8EP 解码的组合。对于不改变现有同构配置的用户,行为完全不变。系统影响:需要对路由器和 proxy 进行相应修改(记录在关联 PR #46115 和 #47495 中)以传递正确的 remote_dp_rank。该 PR 仅处理连接器(decode 端)的读取路由,proxy 端的选择不在本 PR 范围内。团队影响:需要维护两个互相依赖的相关 PR。

核心路径变更 兼容性风险 死锁预防机制 依赖关联 PR

关联 Issue

#46107 [RFC]: Heterogeneous TP<->DP parallelism across the P/D disaggregation boundary (MoRIIO)

完整报告

参与讨论