Prhub

#25988 [diffusion] feat: enable warmup for sglang serve by default

原始 PR 作者 mickqian 合并时间 2026-05-22 08:54 文件变更 7 提交数 12 评论 2 代码增减 +257 / -146

执行摘要

默认启用 diffusion 服务预热,优化首次请求延迟

为了降低 diffusion 模型首次请求的响应时间,避免用户遇到明显的冷启动延迟。PR 标题明确说明启用默认预热。

值得合并。该 PR 有效地解决了 diffusion 服务冷启动问题,设计上优先缓存默认负面提示,并提供了合理的 fallback。建议在后续迭代中增加对预热失败的回退机制和更详细的日志。

讨论亮点

无 review 评论记录,但提交历史显示多次细化迭代,表明对预热缓存逻辑进行了逐步完善。

实现拆解

  1. 在 CLI 入口 serve.py 中,如果用户未显式指定 --warmup,则默认设置为 True。
  2. 在调度器 scheduler.py 中,新增 _logged_server_ready_after_warmup 标记,当所有预热请求完成后输出“服务器就绪”日志。
  3. 核心变更位于 text_encoding.py
    • 新增 get_model_default_negative_prompt 函数,从模型信息中获取默认负面提示。
    • 引入 _should_cache_negative_text_embedding_get_cached_negative_text_embedding_maybe_cache_negative_text_embedding 等方法来精细化控制缓存的写入时机。
    • 关键变化:预热请求也会缓存其编码结果,使得后续真实请求(使用相同默认负面提示时)可以命中缓存,避免重复计算。
  4. 测试方面:更新了 test_text_encoding_cache.py 以验证预热缓存行为;调整了集成测试配置,移除旧的 enable_warmup 字段。
  5. 删除了 testcase_configs.pygpu_cases.py 中与 enable_warmup 相关的代码,简化测试参数。
文件 模块 状态 重要度
python/sglang/multimodal_gen/runtime/pipelines_core/stages/text_encoding.py 文本编码 modified 8.86
python/sglang/multimodal_gen/test/unit/test_text_encoding_cache.py 单元测试 modified 6.49
python/sglang/multimodal_gen/runtime/managers/scheduler.py 调度器 modified 5.16
python/sglang/multimodal_gen/runtime/entrypoints/cli/serve.py CLI 入口 modified 5.16
python/sglang/multimodal_gen/test/server/test_server_common.py 集成测试 modified 3.12
python/sglang/multimodal_gen/test/server/testcase_configs.py 测试配置 modified 3.02
python/sglang/multimodal_gen/test/server/gpu_cases.py GPU 测试 modified 2.48

关键符号

get_model_default_negative_prompt _should_cache_negative_text_embedding _get_cached_negative_text_embedding _maybe_cache_negative_text_embedding _uses_model_default_negative_prompt _get_model_default_negative_prompt _normalize_negative_prompt_for_default_match _append_positive_text_outputs execute_serve_cmd _log_warmup_result

关键源码片段

python/sglang/multimodal_gen/runtime/pipelines_core/stages/text_encoding.py core-logic

重构负面文本编码缓存,支持在预热时缓存默认负面提示,新增模型默认提示获取函数

# 从模型注册表获取默认 negative_prompt,缓存结果避免重复查询
@lru_cache(maxsize=1)
def get_model_default_negative_prompt(
    model_path: str, backend: Any, model_id: str | None
):
    from sglang.multimodal_gen.registry import get_model_info
    model_info = get_model_info(model_path, backend=backend, model_id=model_id)
    if model_info is None:
        return None
    return model_info.sampling_param_cls().negative_prompt
​
​
class TextEncodingStage(PipelineStage):
    # ... 初始化 _negative_text_cache_key / _negative_text_cache_value 等 ...
​
    def get_or_compute_negative_text_embedding(
        self, batch: Req, server_args: ServerArgs, all_indices: list[int]
    ):
        """
        获取缓存的负面文本嵌入,若未命中则计算并视情况缓存。
        预热请求也会缓存,只要使用的 negative_prompt 是模型默认值。
        """
        negative_cache_key = self._build_negative_text_cache_key(
            batch, server_args, all_indices
        )
        cached_negative = self._get_cached_negative_text_embedding(negative_cache_key)
        if cached_negative is not None:
            return cached_negative
​
        negative_text_outputs = self.encode_text(
            batch.negative_prompt,
            server_args,
            encoder_index=all_indices,
            return_attention_mask=True,
        )
        self._maybe_cache_negative_text_embedding(
            negative_cache_key, negative_text_outputs
        )
        return negative_text_outputs
​
    def _should_cache_negative_text_embedding(
        self, batch: Req, server_args: ServerArgs
    ) -> bool:
        # 非预热请求始终缓存;预热请求仅当使用模型默认 negative_prompt 时缓存
        if not batch.is_warmup:
            return True
        return self._uses_model_default_negative_prompt(batch, server_args)
​
    def _get_cached_negative_text_embedding(self, negative_cache_key):
        if negative_cache_key is None:
            return None
        if self._negative_text_cache_key == negative_cache_key:
            return self._negative_text_cache_value
        return None
​
    def _maybe_cache_negative_text_embedding(
        self, negative_cache_key, negative_text_outputs
    ):
        # 外部已决定是否缓存,此处写入缓存
        self._negative_text_cache_key = negative_cache_key
        self._negative_text_cache_value = negative_text_outputs

评论区精华

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

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

风险与影响

  1. 默认启用预热可能增加服务启动时间,对于某些不希望预热的场景(如快速测试)可能需要显式禁用。
  2. 缓存逻辑依赖于 negative_cache_key 的正确性,若 key 构建不完整可能导致缓存误命中。
  3. 新增的 get_model_default_negative_prompt 函数依赖模型注册表,若模型信息缺失则返回 None,此时预热缓存将跳过,行为与未启用预热一致,但需确保日志提示清晰。
  4. 测试覆盖了主要缓存场景,但未覆盖多 encoder 或动态 batch 下的并发缓存行为。

用户侧:使用 sglang serve 启动 diffusion 服务时,首次推理耗时显著降低(预计减少文本编码时间)。系统侧:启动阶段增加约一次文本编码的开销,但后续请求受益。团队侧:简化了配置(不再需要手动指定 --warmup),但默认行为变更可能影响现有单元测试脚本的预期。

默认行为变更 缓存命中依赖 启动时间增加 模型注册表依赖

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论