Prhub

#46990 [ROCm][DeepEP] Stabilize high-throughput DBO for DP+EP

原始 PR 作者 AndreasKaratzas 合并时间 2026-06-30 05:28 文件变更 3 提交数 3 评论 1 代码增减 +42 / -2

执行摘要

修复 ROCm DeepEP 高吞吐 DBO 精度问题

ROCm DeepEP高吞吐DBO在DP+EP模式下GSM8K精度低于测试阈值,原因是异步调度和CU分区导致Buffer共享工作区被提前复用。PR body明确指出测试用例test_dbo_dp_ep_gsm8k[deepep_high_throughput]失败。

建议精读,尤其是_sync_dbo_comm_if_needed的设计模式与CU分区禁用的权衡。该PR展示了在GPU通信与计算重叠场景下,如何通过细粒度同步解决竞态条件,对类似异构并行模式的开发者有参考价值。

讨论亮点

只有一条review评论,来自tlrmchlsmth,建议将错误消息中的备选方案从deepep_low_latency改为更通用的描述,因为低延迟模式批大小受限,不适合作为降级方案。该建议已被采纳并体现在第二个commit中。

实现拆解

  1. 配置层禁止异步调度(vllm/config/vllm.py):在__post_init__中新增uses_rocm_deepep_ht_dbo检测条件,当启用异步调度时直接抛出ValueError;若异步调度为None(自动模式),则警告并禁用异步调度。
  2. 禁用DBO CU分区(vllm/v1/worker/gpu_ubatch_wrapper.py):在_create_sm_control_context中检测rocm_deepep_ht_dbo条件,将comm_sms强制设为0,避免DeepEP高吞吐通信核被CU分区干扰。
  3. 新增同步屏障(vllm/model_executor/layers/fused_moe/prepare_finalize/deepep_ht.py):在DeepEPHTPrepareAndFinalize类中增加_sync_dbo_comm_if_needed方法,在_do_dispatch_finalize调用后执行torch.cuda.current_stream().synchronize(),确保当前ubatch的通信完成后再让下一个ubatch复用Buffer工作区。
  4. 测试配套:无新增测试文件,PR描述提到有单元测试覆盖DBO阈值行为和CU分区保护,但实际提交中测试文件未包含在此PR中。
文件 模块 状态 重要度
vllm/model_executor/layers/fused_moe/prepare_finalize/deepep_ht.py 模型执行器 modified 6.89
vllm/config/vllm.py 配置 modified 6.32
vllm/v1/worker/gpu_ubatch_wrapper.py Worker modified 5.51

关键符号

_sync_dbo_comm_if_needed _create_sm_control_context __post_init__

关键源码片段

vllm/model_executor/layers/fused_moe/prepare_finalize/deepep_ht.py data-contract

核心修复文件,新增同步逻辑确保通信完成后才能复用 Buffer 工作区

class DeepEPHTPrepareAndFinalize(mk.FusedMoEPrepareAndFinalizeModular):
    def __init__(
        self,
        buffer: deep_ep.Buffer,
        num_dispatchers: int,
        dp_size: int,
        rank_expert_offset: int,
    ):
        super().__init__()
        self.buffer = buffer
        self.num_dispatchers_ = num_dispatchers
        self.dp_size = dp_size
        self.rank_expert_offset = rank_expert_offset
        self.async_prepare = True
        # 标记:仅在 ROCm 平台需要同步,避免无谓性能损失
        self.sync_dbo_comm = current_platform.is_rocm()
        self.handles = [None, None]
        self.available_rank_configs = [2, 4, 8, 16, 24, 32, 64, 128, 144, 160]
​
    def _sync_dbo_comm_if_needed(self) -> None:
        # 仅在 DBO 启用且为 ROCm 时同步
        if self.sync_dbo_comm and dbo_enabled():
            # ROCm DeepEP HT dispatch/combine 复用 Buffer 拥有的通信工作区
            # 确保下一个 DBO ubatch 不会在此 ubatch 的 HT kernel 完成前
            # 就开始复用该工作区
            torch.cuda.current_stream().synchronize()
​
    def _do_dispatch(
        self,
        tokens: torch.Tensor,
        token_scales: torch.Tensor | None,
        rank_topk_ids: torch.Tensor,
        # ... 其他参数
    ) -> ...:
        # ... dispatch 逻辑 ...
        # 特别地,async_finish 在 DBO 启用时设为 False
        (token_data, expert_topk_ids, expert_topk_weights,
         expert_num_tokens_per_expert_list, handle, event) = self.buffer.dispatch(
            x=token_data,
            handle=None,
            num_tokens_per_rank=num_tokens_per_rank,
            # ... 其他参数 ...
            async_finish=self.async_prepare and not dbo_enabled(),
            allocate_on_comm_stream=False,
        )
        # 在 dispatch 后立即同步,防止下一个 ubatch 复用工作区
        self._sync_dbo_comm_if_needed()
        # 记录当前 ubatch 的 handle
        a2a_idx = dbo_current_ubatch_id()
        self.handles[a2a_idx] = handle
        # ... 返回结果 ...

评论区精华

错误消息中备选后端的建议 documentation

tlrmchlsmth 建议不要推荐 `deepep_low_latency` 作为降级选项,因为其批大小受限,与高吞吐差异很大

结论:已采纳建议,修改了错误消息,仅提示用户使用 `--no-async-scheduling` 或选择不同的 all2all 后端 · 已解决

风险与影响

  1. 回归风险低:改动仅针对ROCm+DeepEP高吞吐+DBO的组合,通过条件判断隔离,不影响其他平台或后端。
  2. 性能影响:在受影响路径上引入torch.cuda.synchronize()会消除异步重叠优势,但这是保证正确性的必要代价,且仅影响ROCm上特定配置。
  3. 配置兼容性:引入的新异常路径可能导致用户升级时遇到ValueError,但行为明确(显式禁用异步调度即可规避)。

影响范围:仅限ROCm平台上同时启用DeepEP高吞吐和DBO的用户。修复后GSM8K测试从失败变为通过。影响程度:中,因为修复的是正确性而非性能,且配置组合较为特殊。

核心路径变更 缺少测试覆盖

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论