Prhub

#23588 [PD+DP] Allow PrefillDelayer in disaggregated-prefill mode

原始 PR 作者 ByronHsu 合并时间 2026-04-24 05:51 文件变更 2 提交数 1 评论 1 代码增减 +22 / -19

执行摘要

解除 PrefillDelayer 在 disaggregated-prefill 模式下的限制

在disaggregated-prefill + DP attention部署中,多个并发请求被round-robin分发到不同DP rank,导致prefill分两轮执行(第一轮只有DP0,第二轮DP1/2/3),每次都要付出EP all-to-all开销。启用PrefillDelayer后,可以延迟第一轮等待其他rank的请求到来,合并到一次forward中,从而减少EP all-to-all次数。PR body中给出了清晰的性能数据:4并发8192 token请求,端到端耗时从3.023s降到1.957s(~35%更快)。

该PR值得精读,尤其是理解PrefillDelayer的设计原理及其在disaggregated场景下的适配逻辑。变更加少了代码约束,提高了调度组件的灵活性,且性能收益明确。建议合并。

讨论亮点

该PR没有review评论。唯一的审核人ch-wan给予了批准。

实现拆解

  1. prefill_delayer.py 中移除硬断言:删除了第73-75行的 assert server_args.disaggregation_mode == 'null',使得PrefillDelayer在disaggregated-prefill模式下也能通过构造器初始化。保留了对 disable_overlap_schedule 的断言。
  2. scheduler.py 中增加decode引擎的规避逻辑:在 init_schedule_policy 方法中,当启用prefill_delayer时,首先检查 disaggregation_mode 是否为 'decode',如果是则记录一条info日志并跳过构造PrefillDelayer,因为decode引擎没有prefill调度路径。否则正常构造PrefillDelayer。
  3. 无需改动其他代码:PrefillDelayer的协商逻辑(per-iteration all_gather预填充状态、max_delay_passes等待等)对disaggregated-prefill模式同样适用,因此只做了这两处gating调整。
文件 模块 状态 重要度
python/sglang/srt/managers/scheduler.py 调度器 modified 6.85
python/sglang/srt/managers/prefill_delayer.py 调度器 modified 4.99

关键符号

PrefillDelayer.__init__ Scheduler.init_schedule_policy

关键源码片段

python/sglang/srt/managers/scheduler.py core-logic

在 init_schedule_policy 中添加了 decode engine 的条件判断,使 PrefillDelayer 仅在非 decode 模式下构造。

# python/sglang/srt/managers/scheduler.py
# 在 init_schedule_policy 中,构造 PrefillDelayer 时增加对 decode engine 的检查
if self.server_args.enable_prefill_delayer:
    if self.server_args.disaggregation_mode == "decode":
        # decode engine 没有 prefill 调度路径,delayer 不会有任何效果
        logger.info(
            "Ignoring --enable-prefill-delayer on decode engine "
            "(no prefill scheduling path; delayer would be a no-op)."
        )
    else:
        self.prefill_delayer = PrefillDelayer(
            dp_size=self.dp_size,
            attn_tp_size=self.attn_tp_size,
            cpu_group=self.tp_cpu_group,
            server_args=self.server_args,
            metrics_collector=(
                self.metrics_collector if self.enable_metrics else None
            ),
            max_delay_passes=self.server_args.prefill_delayer_max_delay_passes,
            token_usage_low_watermark=self.server_args.prefill_delayer_token_usage_low_watermark,
            device=(
                self.tp_group.device
                if self.server_args.disable_overlap_schedule
                else "cpu"
            ),
        )
python/sglang/srt/managers/prefill_delayer.py core-logic

移除了 disaggregation_mode 必须为 'null' 的断言,使得 PrefillDelayer 在 disaggregated-prefill 模式下能够初始化。

# python/sglang/srt/managers/prefill_delayer.py
# 移除了对 disaggregation_mode 的检查,允许在 prefill 模式下使用
self._curr_state: Optional[_State] = None
self.skip_first_delayer = True# 已删除:assert server_args.disaggregation_mode == "null"
# 保留了对 disable_overlap_schedule 的断言
assert (
    not server_args.disable_overlap_schedule
), "To use PrefillDelayer, disable_overlap_schedule must be False."

评论区精华

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

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

风险与影响

  1. 回归风险低:变更仅移除了一个断言并增加了一个条件分支,没有修改任何模型前向逻辑或kernel。在非disaggregated场景('null'模式)下行为不变。
  2. 潜在的性能影响:在decode engine上忽略enable_prefill_delayer是安全的,因为该标志仅用于prefill engine。但需确保用户不会误认为在decode engine上启用了该功能——日志记录已清晰说明。
  3. 兼容性:现有 --prefill-delayer-max-delay-passes--prefill-delayer-token-usage-low-watermark 参数无需改动,在prefill engine上正常工作。

影响范围:主要影响使用disaggregated-prefill + DP attention的用户(如Qwen3-30B-A3B等模型)。影响程度:对于此类部署,可以显著减少EP all-to-all开销,提升prefill吞吐(实验显示端到端延迟降低约35%)。对于非disaggregated或decode engine用户,无任何影响。无需文档更新或配置变更。

核心路径变更 影响面受控 无测试覆盖

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论