Prhub

#44074 [Core] Pluggable sleep-mode backend abstraction (RFC #34303)

原始 PR 作者 matteso1 合并时间 2026-07-01 13:00 文件变更 4 提交数 1 评论 14 代码增减 +309 / -4

执行摘要

引入可插拔 sleep 模式后端抽象,默认行为不变

冷启动延迟是 multi-model serving、scale-to-zero serverless 和 cost-efficient hosting 的主要障碍(RFC #34303)。CUDA checkpoint/restore 可以消除权重传输、torch.compile 和 CUDA graph 捕获等昂贵步骤。本 PR 引入后端抽象,使得不同机制(cumem、CUDA checkpoint 等)可以按名称选择,无需修改公共 API,从而解锁 RFC 的 Phase 1/2。

值得精读。该 PR 的设计模式(可插拔后端 ABC + 工厂 + 能力标志)是 vLLM 中类似 attention backend 模式的延续,可以作为其他需要多后端支持的场景(如 KV 传输、调度)的参考。对于想贡献新 sleep 后端的开发者,这是必读的接口规范。

讨论亮点
  • 测试文件位置:simon-mo 要求将测试文件移到合适目录,作者将其从 tests/ 移到 tests/v1/worker/
  • 能力标志命名的通用性:galletas1712(NVIDIA Dynamo 团队)质疑 preserves_nccl 等 NCCL 特定命名是否过于狭窄,因为 vLLM 还有其他通信后端。aoshen02 认为名称反映了已知场景,可以未来扩展。作者回应这些标志是通用意图,命名反映了当前实现细节,可随新需求扩展。最终保持原有设计。
  • 外部团队期待:Alibaba ACK 和 NVIDIA Dynamo 团队均表达了对该 PR 的迫切需求,希望它尽快合并以解锁各自的下游工作。

实现拆解

  1. 定义抽象接口:在 vllm/device_allocator/sleep_mode_backend.py 中新建 SleepModeBackend ABC,包含 suspend/resume 抽象方法和 state() 方法,以及五个类方法能力标志(is_supported, preserves_nccl, preserves_compiled_artifacts, preserves_graphs_with_nccl, supports_durable_storage)。
  2. 实现默认后端CuMemBackend 包装现有 CuMemAllocator 的 sleep/wake_up 调用,保持行为一致。同时设置适当的能力标志(NCCL 保持,编译工件不保持等)。
  3. 工厂注册机制SleepModeBackendFactory 类似 KVConnectorFactory,支持按名称注册后端(模块路径 + 类名),第三方可通过 vllm.general_plugins 入口点注册。
  4. 配置集成:在 vllm/config/model.pyModelConfig 中添加 sleep_mode_backend: str = "cumem" 字段,自动暴露为命令行参数。
  5. GPU Worker 集成:在 vllm/v1/worker/gpu_worker.py 中添加 _get_sleep_mode_backend() 懒加载方法,替换原有的直接 get_mem_allocator_instance().sleep/wake_up 调用为通过工厂创建的后端实例的方法。
  6. 测试配套:新增 tests/v1/worker/test_sleep_mode_backend.py,包含 7 个 CPU 端单元测试,覆盖默认注册、能力标志、未知后端错误、重复注册保护、第三方注册/解析以及状态转换。GPU 端集成测试由现有 tests/basic_correctness/test_cumem.py 覆盖。
文件 模块 状态 重要度
vllm/device_allocator/sleep_mode_backend.py sleep 后端 added 9.0
vllm/v1/worker/gpu_worker.py 工作器 modified 6.55
vllm/config/model.py 配置 modified 4.94
tests/v1/worker/test_sleep_mode_backend.py sleep 后端测试 added 7.42

关键符号

SleepModeBackend.suspend SleepModeBackend.resume SleepModeBackend.state CuMemBackend.suspend CuMemBackend.resume SleepModeBackendFactory.create_backend SleepModeBackendFactory.get_backend_class GPUWorker._get_sleep_mode_backend GPUWorker.sleep GPUWorker.wake_up

关键源码片段

vllm/device_allocator/sleep_mode_backend.py dependency-wiring

核心新文件,定义 SleepModeBackend ABC、默认 CuMemBackend 实现和工厂类,是整个 PR 的核心抽象。

# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
"""可插拔 sleep-mode 后端(RFC #34303)。"""
from __future__ import annotations
import importlib
from abc import ABC, abstractmethod
from collections.abc import Callable
from typing import TYPE_CHECKING, Literal
from vllm.logger import init_loggerif TYPE_CHECKING:
    from vllm.config.model import ModelConfiglogger = init_logger(__name__)# 生命周期状态:运行中、已挂起、正在恢复
SleepModeState = Literal["RUNNING", "SUSPENDED", "RESUMING"]class SleepModeBackend(ABC):
    """GPU 状态释放与恢复机制的统一接口。
    每个后端拥有自己的 suspend/resume 实现;
    调度路径(/sleep 端点 -> engine -> executor -> worker)共享。
    能力标志为类方法,允许在未实例化时查询后端特性。
    """
    def __init__(self) -> None:
        self._state: SleepModeState = "RUNNING"
​
    @abstractmethod
    def suspend(self, level: int = 1) -> None:
        """释放 GPU 状态。
        level 1: 将权重卸载到主机 RAM(可在进程内恢复)。
        level 2: 丢弃权重(从模型源重新加载)。
        """
        raise NotImplementedError
​
    @abstractmethod
    def resume(self, tags: list[str] | None = None) -> None:
        """恢复之前挂起的 GPU 状态。
        tags 可选地限制恢复的分配(例如 ["weights"] 或 ["kv_cache"])。
        """
        raise NotImplementedError
​
    def state(self) -> SleepModeState:
        """返回当前生命周期状态,/health 端点可据此区分空闲挂起引擎与正常服务引擎。"""
        return self._state
​
    # 能力标志(无需实例即可查询)
    @classmethod
    def is_supported(cls) -> bool:
        """当前平台是否支持此后端。"""
        return True
​
    @classmethod
    def preserves_nccl(cls) -> bool:
        """suspend 后 NCCL 通信器是否仍然有效。默认 False,需执行器重建。"""
        return False
​
    @classmethod
    def preserves_compiled_artifacts(cls) -> bool:
        """torch.compile / JIT 内核在 suspend/resume 后是否保留。"""
        return False
​
    @classmethod
    def preserves_graphs_with_nccl(cls) -> bool:
        """包含 NCCL 集合的 CUDA 图在恢复后是否仍有效。"""
        return False
​
    @classmethod
    def supports_durable_storage(cls) -> bool:
        """挂起状态是否可以持久化到进程生命周期之外(磁盘或对象存储)。"""
        return False
vllm/v1/worker/gpu_worker.py core-logic

修改 sleep/wake_up 方法,引入后端分发,是抽象层的消费者。

# 在 GPUWorker.__init__ 中新增后端字段,懒加载
self._sleep_mode_backend: SleepModeBackend | None = Nonedef _get_sleep_mode_backend(self) -> "SleepModeBackend":
    """通过工厂懒加载后端实例,后续调用复用。"""
    if self._sleep_mode_backend is None:
        from vllm.device_allocator.sleep_mode_backend import SleepModeBackendFactory
        self._sleep_mode_backend = SleepModeBackendFactory.create_backend(
            self.vllm_config.model_config
        )
    return self._sleep_mode_backenddef sleep(self, level: int = 1) -> None:
    torch.accelerator.synchronize()
    # ... 其他代码(buffer 保存等)...
    # 替换原有直接 allocator 调用为后端抽象
    self._get_sleep_mode_backend().suspend(level)
    # ... 后续同步和内存检查 ...def wake_up(self, tags: list[str] | None = None) -> None:
    # 替换原有 allocator 调用
    self._get_sleep_mode_backend().resume(tags)
    # ... buffer 恢复等 ...

评论区精华

测试文件位置 测试

simon-mo 要求将测试文件移到合适目录,而不是放在 tests/ 根目录。

结论:作者将文件移到 tests/v1/worker/ 并更新了导入路径。 · 已解决

能力标志命名和通用性 设计

galletas1712 质疑 preserves_nccl 等标志过于 NCCL 特定,可能不够通用。aoshen02 认为名称反映了已知场景。作者回应这些标志是设计意图,名称反映当前实现细节,未来可扩展。

结论:保持原设计,未修改。 · 已解决

风险与影响

由于是纯抽象重构且默认行为不变,风险极低。主要风险在于:如果第三方后端注册配置错误,可能导致 sleep/wake_up 失败,但工厂代码已经包含错误抛出和测试覆盖。能力标志如果设置错误,可能导致调度器或 health 检查误判,但会在后端开发阶段被发现。

  • 用户影响:无。现有用户继续使用 --enable-sleep-mode,行为不变。
  • 系统影响:为未来多种 sleep 机制提供扩展点,降低后续后端的接入成本。
  • 团队影响:需要了解新的后端抽象和工厂机制,但文档充分(注释中引用 RFC)。
核心路径变更 新扩展点

关联 Issue

#34303 [RFC]: CUDA Checkpoint/Restore for Near-Zero Cold Starts

完整报告

参与讨论