Prhub

#29514 [diffusion] fix --warmup silently downgrading server-based warmup to request mode

原始 PR 作者 mickqian 合并时间 2026-06-28 11:46 文件变更 2 提交数 3 评论 1 代码增减 +25 / -0

执行摘要

修复 --warmup 静默降级为 request 模式

PR body 明确指出 sglang serve --warmup 本应使用 server-based warmup,但因 serve 注入的 warmup_mode="server" 通过 default_args 传递且未被记录为显式参数,导致 _adjust_warmup 中条件判断 mode_explicit or not legacy_explicitFalse,结果 server_warmup 回退到 dataclass 默认值 False(即 request 模式)。组合 --warmup --warmup-resolutions 时更形成死区:server warmup 不跑,request warmup 因 resolutions 非 None 也跳过,最终无任何 warmup 执行,首个请求承担 ~2× 冷启动延迟。

值得合并。这是一个典型的“配置继承边界”bug:default_args 未记录为 explicit 导致注入的默认值与显式标志交互异常。PR 分析透彻、修复精准、单测完备,且 H100 实测数据验证有效。值得其他 CLI 参数解析模块参考此模式(default_args 与 explicit 标志的一致性)。

讨论亮点

仅有一条自动 Code Review 评论来自 gemini-code-assist[bot],确认变更正确且无 review 意见。无人工 review 讨论。PR 作者 @mickqian 在 body 中详尽分析了根因和修复逻辑,并提供了 H100 实测数据:修复后 Z-Image-Turbo 从 13.46s(无 warmup)降至 0.74s(vs baseline 0.65s),其余 diffusion 模型也恢复至 baseline 水平。

实现拆解

  1. 入口python/sglang/multimodal_gen/runtime/server_args.py_adjust_warmup 方法负责解析 warmup 相关参数,决定 self.warmupself.server_warmup
  2. 原逻辑分支if mode_explicit or not legacy_explicit: 已处理了两种 case:显式指定了 --warmup-mode,或 legacy 标志未显式。漏掉的是 legacy 标志显式(如 --warmup)但 warmup_mode 未显式(由 serve 注入默认值)的 case,降级为 request 模式。
  3. 修复:在该分支后新增 elif self.warmup: 分支,当 legacy 标志显式且 warmup 被启用时,设置 self.server_warmup = self.server_warmup or self.warmup_mode == "server",此处 self.warmup_mode 保留的是 "server"None 等已解析值,从而正确启用 server warmup。
  4. 测试配套:在 test_server_args.pyTestWarmupModeNormalization 类中新增两个测试用例:test_legacy_warmup_on_uses_defaulted_server_mode 验证 --warmup 带默认 server mode 时正确设置 server_warmup=Truetest_legacy_warmup_with_resolutions_runs_server_warmup 验证死区回归:--warmup --warmup-resolutions 时执行 server warmup。
  5. 配套变更:无其他配置或部署变更。仅 2 行源码 + 23 行测试,改动极小。
文件 模块 状态 重要度
python/sglang/multimodal_gen/test/unit/test_server_args.py 测试 modified 5.94
python/sglang/multimodal_gen/runtime/server_args.py 服务器参数 modified 5.1

关键符号

_adjust_warmup

关键源码片段

python/sglang/multimodal_gen/test/unit/test_server_args.py test-coverage

新增两个单元测试,验证修复的正确性并防止回归:test_legacy_warmup_on_uses_defaulted_server_mode 和 test_legacy_warmup_with_resolutions_runs_server_warmup。覆盖了最关键的死区回归场景。

def test_legacy_warmup_on_uses_defaulted_server_mode(self):
    # `serve --warmup` (legacy ON, mode defaulted to "server" but not
    # explicit) must resolve to server-based warmup, not silently downgrade
    # to request mode.
    sa = self._resolve(
        warmup_mode="server", # 由 serve CLI 注入默认值
        warmup=True,
        explicit=("warmup",), # 仅 --warmup 显式传入
    )
    self.assertEqual(sa.warmup_mode, "server")
    self.assertTrue(sa.warmup)
    self.assertTrue(sa.server_warmup)def test_legacy_warmup_with_resolutions_runs_server_warmup(self):
    # Dead-zone regression: `serve --warmup --warmup-resolutions X` must run
    # server-based (synthetic) warmup, not end up with no warmup at all
    # (request-based warmup bails out when warmup_resolutions is set).
    sa = self._resolve(
        warmup_mode="server",
        warmup=True,
        warmup_resolutions=["1024x1024"],
        explicit=("warmup",),
    )
    self.assertTrue(sa.warmup)
    self.assertTrue(sa.server_warmup)
    self.assertEqual(sa.warmup_mode, "server")
python/sglang/multimodal_gen/runtime/server_args.py core-logic

核心修复文件。在 _adjust_warmup 方法中新增 elif 分支,处理 legacy 标志显式而 warmup_mode 未显式时的 server_warmup 赋值。仅 +2 行代码。

def _adjust_warmup(self):
    # --warmup-mode > --warmup/--server-warmup
    mode_explicit = self.is_arg_explicitly_set("warmup_mode")
    legacy_explicit = self.is_arg_explicitly_set(
        "warmup"
    ) or self.is_arg_explicitly_set("server_warmup")
    if self.warmup_mode is not None:
        if self.warmup_mode not in WARMUP_MODES:
            raise ValueError(
                f"Invalid --warmup-mode {self.warmup_mode!r}; "
                f"expected one of {WARMUP_MODES}."
            )
        if mode_explicit and legacy_explicit:
            logger.warning(
                "Both --warmup-mode and the deprecated --warmup/--server-warmup "
                "were set; --warmup-mode=%s takes precedence.",
                self.warmup_mode,
            )
        if mode_explicit or not legacy_explicit:
            # mode_explicit: 用户显式指定 --warmup-mode,直接使用
            # not legacy_explicit: 无 legacy 标志,直接用 warmup_mode(如 bare `serve` 注入的默认值)
            self.warmup = self.warmup_mode != "off"
            self.server_warmup = self.warmup_mode == "server"
        elif self.warmup:
            # [!] 新增分支:legacy 标志显式(如 --warmup)但 warmup_mode 未显式
            # 此时应沿用已解析的 warmup_mode(如 serve 注入的 "server")
            self.server_warmup = self.server_warmup or self.warmup_mode == "server"
​
    # Explicit resolutions imply warmup is on (request-based).
    if self.warmup_resolutions is not None:
        self.warmup = True
​
    if self.disagg_role != RoleType.MONOLITHIC:
        self.server_warmup = False
​
    if not self.warmup:
        self.server_warmup = False
​
    self.warmup_mode = (
        "off" if not self.warmup
        else "server" if self.server_warmup
        else "request"
    )

评论区精华

自动 Code Review 确认无额外意见 other

gemini-code-assist[bot] 自动 review 表示无 review 意见,确认变更正确。

结论:无额外修改需求。 · 已解决

风险与影响

风险极低:

  • 仅新增一个 elif self.warmup: 分支,不会影响已有分支逻辑(warmup 为 False 时跳过,与之前行为一致)。
  • 单测覆盖了 legacy 显式 + 默认 server mode、legacy + resolutions 两种关键路径。
  • 改动涉及 server args 解析,属冷启动路径,不影响推理运行时。
  • _adjust_warmup 中逻辑分支较多,需确保无其他未覆盖的组合(如 --server-warmup 不带 --warmup-mode)。现有单测已涵盖 --warmup false 和 bare serve 等场景,回归风险小。

用户影响:修复后 sglang serve --warmup--warmup --warmup-resolutions 正确执行 server-based warmup,diffusion 模型首个请求延迟降低约 50%-90%(如 Z-Image-Turbo 从 13.46s 降至 0.74s)。所有依赖 CLI warmup 的 diffusion 用户受益。
系统影响:无性能或内存影响。
团队影响:降低因 warmup 配置陷阱导致的 debug 成本。

分支逻辑嵌套需谨慎 单测覆盖充分

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论