Prhub

#33850 [diffusion] retire released warmup and decoder flags

原始 PR 作者 mickqian 合并时间 2026-08-06 23:02 文件变更 19 提交数 1 评论 3 代码增减 +143 / -304

执行摘要

退役旧预热与 decoder_tp 参数,统一为 warmup_mode

PR body 明确指出:“The deprecated flags have passed their supported migration window and retaining them obscures the real configuration model.” 即 --warmup/--server-warmup/--decoder-tp 的兼容迁移窗口已结束,继续保留会掩盖真实的配置模型(warmup_modedecoder_sp),因此选择直接移除并统一所有调用点。

值得精读 server_args.py_reject_retired_args_adjust_warmup,这是“参数退役”的可借鉴范式:先双轨兼容 → 到期后硬拒绝并给出替代提示,避免长期维护两套配置语义。建议关注两点:一是 release notes 中明确标注 breaking change;二是观察外部用户迁移反馈,必要时提供一段临时兼容告警而非直接报错。整体属于高信号的安全清理型重构。

讨论亮点

本 PR 没有收到实质性 review 评论(review_comments_count 为 0)。3 条 issue 评论均为作者 mickqian 自己触发的 CI 命令 /tag-and-rerun-ci/tag-and-rerun-ci extra,对应 PR body 中的“Remote CI lint was triggered with /tag-and-rerun-ci; no local tests were run under the SGLang-Diffusion guidance”。作者自审自合(author 与 merged_by 均为 mickqian),关键决策(直接报错拒绝而非继续降级兼容)未经过外部 reviewer 质询,风险主要由常规 + extra 两套远程 CI 覆盖。

实现拆解

变更以 python/sglang/multimodal_gen/runtime/server_args/server_args.py 为入口,按以下 5 步完成:

  1. 删除退役参数的定义与 CLI 入口:在 ServerArgs 数据类中删除 warmupserver_warmupdecoder_tp 三个字段;在 server_args/disagg.py 中删除 --decoder-tp 参数;在 add_cli_args 中删除 --warmup--server-warmup 两个参数定义。这样 CLI 用户再传旧参数会直接得到 argparse 的 unrecognized arguments 错误。

  2. 新增硬校验 _reject_retired_args:在 from_dict 开头调用该静态方法,维护“退役参数 → 替代写法”的映射(decoder_tp → decoder_spwarmup → warmup_mode=request/offserver_warmup → warmup_mode=server),命中即抛 ValueError。同时删除 _adjust_disagg_parallelism_aliases,不再做静默别名转换。

  3. 简化 _adjust_warmup:删除从两个布尔字段推导 warmup_mode 的旧逻辑,改为只围绕 warmup_mode 做归一化:非法值校验 → enable_torch_compile 默认 server → 显式 warmup_resolutions 触发 request → BCG 强制 server → 非 monolithic 角色把 server 降级为 request → 最终 None 默认 off

  4. 切换运行时查询点:所有读取 server_args.warmup / server_args.server_warmup 的地方改为读取 warmup_mode。包括 server_warmup.pyshould_run_server_warmupshould_run_explicit_client_warmupprocess_received_reqs_with_req_based_warmuplaunch_server.py 的 disagg 角色 role_overrideshttp_server.py 的 lifespan 预热任务启动条件;denoising.py_maybe_offload_during_compilediffusion_generator.py_log_summary;benchmark 脚本 bench_diffusion_denoise.pybuild_sglang_cmd 与参数对齐校验。disagg 角色中 warmup=True + server_warmup=False 的组合被等价替换为 warmup_mode="request"(encoder 角色)和 warmup_mode="off"(其他角色),语义保持一致。

  5. 测试与文档配套test_server_args.py 重写 TestWarmupModeNormalization(去掉 legacy 布尔分支测试,新增 BCG 强制 server 的用例),并新增 test_retired_warmup_config_is_rejectedtest_retired_warmup_kwargs_are_rejected 两个硬校验测试;test_cfg_parallel_warmup.py 将 fixture 从布尔字段改为 warmup_modegen_perf_baselines.pytest_pi05_e2e.pygpu_cases.py 同步;.claude/skills 下的 SKILL.md、benchmark-and-profile.md 以及 docs/docs/sglang-diffusion/ 下多处 mdx 文档同步替换为 --warmup-mode / --decoder-sp

文件 模块 状态 重要度
python/sglang/multimodal_gen/runtime/server_args/server_args.py 服务参数 modified 8.01
python/sglang/multimodal_gen/test/unit/test_server_args.py 参数测试 modified 7.09
python/sglang/multimodal_gen/runtime/launch_server.py 启动器 modified 5.35
python/sglang/multimodal_gen/runtime/server_warmup.py 预热逻辑 modified 5.07
python/sglang/multimodal_gen/runtime/server_args/disagg.py 分解参数 modified 4.79
python/sglang/multimodal_gen/.claude/skills/sglang-diffusion-benchmark-profile/scripts/bench_diffusion_denoise.py 基准脚本 modified 4.67

关键符号

_adjust_warmup _reject_retired_args _adjust_disagg_parallelism_aliases should_run_server_warmup should_run_explicit_client_warmup should_run_synthetic_server_warmup process_received_reqs_with_req_based_warmup

关键源码片段

python/sglang/multimodal_gen/runtime/server_args/server_args.py core-logic

核心变更文件:删除退役字段与 CLI 参数,新增 _reject_retired_args 硬校验,并重构 _adjust_warmup 为纯 warmup_mode 推导。

def _adjust_warmup(self):
    """将 `warmup_mode` 归一化为唯一的预热控制信号。    取值来自 `WARMUP_MODES`("off" / "server" / "request");
    运行时特征(torch.compile、BCG、disagg 角色)只能在这里推导或修正该值,
    不再维护派生的布尔字段 `warmup` / `server_warmup`。
    """
    if self.warmup_mode is not None and self.warmup_mode not in WARMUP_MODES:
        raise ValueError(
            f"Invalid --warmup-mode {self.warmup_mode!r}; "
            f"expected one of {WARMUP_MODES}."
        )
​
    # torch.compile 希望启动期完成编译,否则首个真实请求会承担编译延迟。
    if self.enable_torch_compile and self.warmup_mode is None:
        self.warmup_mode = "server"
        logger.info(
            "Automatically enabled server warmup for torch.compile so first "
            "real requests do not pay compile latency. Set --warmup-mode off "
            "to disable this behavior."
        )
​
    # 显式声明分辨率时至少需要 request 级预热;若用户已选 server 则保留。
    if self.warmup_resolutions is not None and self.warmup_mode in (None, "off"):
        self.warmup_mode = "request"
​
    # BCG 需要在启动期用合成请求捕获全部 CUDA Graph,因此强制 server 模式。
    if self.enable_breakable_cuda_graph and self.disagg_role == RoleType.MONOLITHIC:
        self.warmup_mode = "server"
​
    # 解耦角色不承载 HTTP 启动请求,server 预热降级为首个请求预热。
    if self.disagg_role != RoleType.MONOLITHIC and self.warmup_mode == "server":
        self.warmup_mode = "request"
​
    if self.warmup_mode is None:
        self.warmup_mode = "off"
​
​
@staticmethod
def _reject_retired_args(kwargs: dict[str, Any]) -> None:
    """在 `from_dict` / `from_kwargs` 入口拒绝已退役的兼容参数。    旧参数迁移窗口已过,继续接受只会掩盖真实的配置模型;这里直接抛错,
    并给出替代写法,让外部调用方快速迁移到 `warmup_mode` 与 `decoder_sp`。
    """
    retired = {
        "decoder_tp": "decoder_sp for decoder/VAE parallel decode",
        "warmup": "warmup_mode=request or warmup_mode=off",
        "server_warmup": "warmup_mode=server",
    }
    for arg, replacement in retired.items():
        if arg in kwargs:
            raise ValueError(
                f"{arg} is retired; use {replacement} instead."
            )
python/sglang/multimodal_gen/test/unit/test_server_args.py test-coverage

测试配套:重写 TestWarmupModeNormalization 并新增退役参数拒绝测试,验证 from_dict/from_kwargs 对新契约的强制行为。

class TestWarmupModeNormalization(unittest.TestCase):
    """`_adjust_warmup` 现在只解析规范的 `warmup_mode`,不再有 legacy 布尔分支。"""
​
    def _resolve(
        self,
        *,
        warmup_mode=None,
        warmup_resolutions=None,
        enable_torch_compile=False,
        enable_breakable_cuda_graph=False,
        disagg_role=None,
    ):
        from sglang.multimodal_gen.runtime.disaggregation.roles import RoleType
​
        sa = ServerArgs.__new__(ServerArgs)
        sa.warmup_mode = warmup_mode
        sa.warmup_resolutions = warmup_resolutions
        sa.enable_torch_compile = enable_torch_compile
        sa.enable_breakable_cuda_graph = enable_breakable_cuda_graph
        sa.disagg_role = RoleType.MONOLITHIC if disagg_role is None else disagg_role
        sa._adjust_warmup()
        return sa
​
    def test_breakable_cuda_graph_forces_server_warmup(self):
        # BCG 需要启动期捕获全部 CUDA Graph,必须走 server 合成预热。
        sa = self._resolve(enable_breakable_cuda_graph=True)
        self.assertEqual(sa.warmup_mode, "server")
​
    def test_disagg_role_disables_server_warmup(self):
        # 解耦角色不承载 HTTP 启动请求,server 预热降级为 request。
        from sglang.multimodal_gen.runtime.disaggregation.roles import RoleType
​
        sa = self._resolve(
            warmup_mode="server",
            disagg_role=RoleType.DENOISER,
        )
        self.assertEqual(sa.warmup_mode, "request")
python/sglang/multimodal_gen/runtime/launch_server.py core-logic

disagg 池启动器:把各角色 role_overrides 中的 warmup/server_warmup 布尔组合替换为 warmup_mode,保证分解部署语义不变。

# 为每个 disagg 角色实例构造覆盖参数;并行度全部由 get_role_parallelism 统一推导。
role_overrides = {
    "disagg_role": role_type,
    "disagg_mode": True,
    "pool_work_endpoint": work_eps[inst_idx],
    "pool_result_endpoint": result_ep,
    "num_gpus": num_role_gpus,
    # 仅 encoder 角色执行预热(request 模式,等价于旧的 warmup=True + server_warmup=False);
    # denoiser / decoder 角色在分解池中不预热。
    "warmup_mode": "request" if role_type == RoleType.ENCODER else "off",
    "scheduler_port": find_port(port_cursor),
    "master_port": find_port(port_cursor + 100),
}base_dict.update(role_overrides)
base_dict.pop("pipeline_config", None)
role_args = ServerArgs.from_kwargs(**base_dict)

评论区精华

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

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

风险与影响

  1. 破坏性参数移除:所有仍传 --warmup--server-warmup--decoder-tp 的 CLI 用户会立即因 argparse 报 unrecognized arguments;通过配置文件或 ServerArgs.from_dict/from_kwargs 传入旧键会触发 _reject_retired_argsValueError。仓库内调用点已全部更新,但仓库外的脚本、部署配方未纳入管控,需要发布说明高亮该 breaking change。
  2. disagg 角色语义保持launch_server.py 中 encoder 角色从 warmup=True + server_warmup=False 改写为 warmup_mode="request",与原语义等价;但若外部代码隐式依赖过“unset 时 warmup 默认行为”,可能受影响。_adjust_warmup 中 BCG 先设 server、disagg 再降级为 request 的顺序保证了非 monolithic 角色不会执行 HTTP 启动预热。
  3. 测试覆盖依赖单测与 CI:本地未跑测试,依赖远程 CI(Run #31109524523 常规 + #31109523671 extra)验证,test_server_args.py 对退役参数拒绝路径有直接覆盖,但未覆盖所有历史组合的迁移场景。

用户影响:使用 SGLang Diffusion 的所有 CLI 用户与配置中心必须从 --warmup/--server-warmup/--decoder-tp 迁移到 --warmup-mode/--decoder-sp,属于用户可见的破坏性变更。系统影响:消除了布尔字段与枚举字段双轨并存的配置模型,_adjust_warmup 逻辑显著简化,运行时查询点统一为单一枚举判断,降低后续误用风险。团队影响:作为近期 diffusion hygiene 系列(33843-33845 等)的一部分,继续收敛配置面与入口面,为后续扩散功能迭代提供更干净的参数基础。

破坏性参数移除 CLI 行为变更 配置契约变更 无外部 review

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论