引言

多模型推理服务难题: 你有两个 LLM,每个都能装进 GPU,但无法同时装入。传统的解决方案被迫在两个糟糕的选择中权衡:

  1. 保持两个模型同时加载 → 需要 2 倍的 GPU 显存(昂贵,且通常不可行)
  2. 按需重新加载模型 → 每次切换需要 30-100+ 秒(缓慢,且浪费资源)

vLLM Sleep Mode

vLLM 睡眠模式提供了第三种选择: 模型在几秒钟内进入休眠并能快速唤醒——既拥有按需加载的高效率,又具备持久服务的响应速度。

两种睡眠级别满足不同需求

  • 级别 1 (Level 1): 将权重卸载到 CPU RAM(唤醒速度极快)
  • 级别 2 (Level 2): 完全丢弃权重(唤醒速度几乎同样快,CPU 内存占用极低)

两种级别都比完整重载快 18-200 倍,并能与张量并行 (TP)、流水线并行 (PP) 和专家并行 (EP) 无缝协作。

为什么睡眠模式优于快速权重加载器

即使拥有即时的权重加载能力,每次冷启动都会产生一些睡眠模式可以避免的隐藏成本:

成本项 描述 快速权重加载器 睡眠模式
1. VRAM 加载时间 将权重复制到 GPU ✅ 已优化 ✅ 已保留
2. 内存分配器设置 CUDA 分配器初始化 ❌ 每次都要执行 ✅ 已保留
3. CUDA 图捕获 记录执行图 ❌ 每次都要执行 ✅ 已保留
4. GPU 算子 JIT 编译 DeepGEMM, FlashInfer, TorchInductor ❌ 每次都要执行 ✅ 已保留(初始预热后)
5. 缓存预热 首条请求开销 ❌ 每次都要执行 ⚡ 快速重预热

通过保持进程存活,睡眠模式保留了基础设施(第 2-4 项)并避免了昂贵的重新初始化。这就是为什么基准测试显示睡眠模式的推理速度比冷启动快 61-88%

本文涵盖内容

  • 跨模型规模(0.6B 到 235B)和 GPU(A4000 到 A100)的综合基准测试
  • 解释性能提升的技术深度解析
  • 关于预热影响和 FP8 量化的消融研究
  • 选择合适睡眠级别的决策指南

快速入门:使用睡眠模式

在线服务 API

启动两个启用了睡眠模式的 vLLM 服务器

# Terminal 1: Start Phi-3-vision
export VLLM_SERVER_DEV_MODE=1
vllm serve microsoft/Phi-3-vision-128k-instruct --enable-sleep-mode --port 8001

# Terminal 2: Start Qwen3-0.6B
export VLLM_SERVER_DEV_MODE=1
vllm serve Qwen/Qwen3-0.6B --enable-sleep-mode --port 8002

使模型休眠与唤醒

# Put Phi-3-vision to sleep (Level 2 - minimal RAM usage)
curl -X POST 'localhost:8001/sleep?level=2'

# Put Qwen3-0.6B to sleep (Level 2)
curl -X POST 'localhost:8002/sleep?level=2'

# Wake up Phi-3-vision for inference
curl -X POST 'localhost:8001/wake_up'
curl -X POST 'localhost:8001/collective_rpc' \
  -H 'Content-Type: application/json' \
  -d '{"method":"reload_weights"}'

# IMPORTANT: Reset prefix cache after waking (Level 2 only)
curl -X POST 'localhost:8001/reset_prefix_cache'

# Now run inference on Phi-3-vision...
# (your inference requests here)

# Put back to sleep when done
curl -X POST 'localhost:8001/sleep?level=2'

# Wake up Qwen3-0.6B
curl -X POST 'localhost:8002/wake_up'
# (Level 1 doesn't need reload_weights or reset_prefix_cache)

# Run inference on Qwen3-0.6B...

说明

对于级别 2 睡眠,唤醒后必须调用 reload_weightsreset_prefix_cache。级别 1 睡眠不需要这些额外步骤。

警告

安全提示: /sleep/wake_up/collective_rpc/reset_prefix_cache 端点需要设置 VLLM_SERVER_DEV_MODE=1,且应仅在信任网络中开放。这些管理端点可能会干扰服务,适用于训练集群或后端应用等封闭环境。

性能概览

让我们看看睡眠模式与传统模型重载的性能对比。

睡眠模式 L1 与无睡眠模式性能对比

下方的交互式图表显示了执行 5 次模型切换的总时间:在模型 A 上运行推理,切换到模型 B,在模型 B 上运行推理,然后重复此模式(A→B→A→B→A→B)。

使用睡眠模式: 模型在切换间隙休眠/唤醒,保留了基础设施。不使用睡眠模式: 每次切换都需要完整的 vLLM 重启和重载。

模型 A: Qwen3-235B-A22B-Instruct-2507-FP8 (TP=4) | 模型 B: Qwen3-Coder-30B-A3B-Instruct (TP=1)
GPU: A100 | vLLM 0.11.0 | 睡眠级别: 1 | 编译设置: cudagraph_mode: FULL_AND_PIECEWISE

推理性能提升

除了更快的模型切换外,睡眠模式还带来了更快的推理时间。因为模型从睡眠中唤醒时已经完成了预热,它们跳过了影响新加载模型的冷启动开销。

唤醒模式(已预热)与冷启动(刚加载)的推理时间对比。
推理时间 = Prefill + Decode(唤醒/加载后的第一条请求)。 每个请求使用不同的问题以避免缓存影响,输出限制为 100 个 token。
误差线显示了多次运行中的最小/最大变化。数值显示在柱状图上。
GPU: A100 | vLLM 0.11.0 | 睡眠级别: 1 | 编译设置: cudagraph_mode: FULL_AND_PIECEWISE

为什么睡眠模式能提高推理速度

61-88% 的推理提速并非源于更快的权重加载,而是源于保留了冷启动必须从头构建的昂贵基础设施

睡眠模式保留了什么

组件 是否保留? 冷启动必须付出的代价
内存分配器 (CuMemAllocator) ✅ 是 ❌ 每次都要重新初始化
CUDA 图 (CUDA graphs) ✅ 是 ❌ 每次都要重新捕获
进程状态 (Python, CUDA 上下文) ✅ 是 ❌ 每次都要重启
GPU 算子 JIT 缓存 ✅ 是(初始预热后) ❌ 每次都要重新编译

核心差异

  • 不使用睡眠模式: 卸载时进程结束 → 你无法从预热中受益
    • 必须重启 Python 进程和 CUDA 上下文
    • 必须重新初始化内存分配器
    • 必须重新捕获 CUDA 图
    • 必须重新 JIT 编译算子(DeepGEMM, FlashInfer, TorchInductor)
    • 结果: 首次推理速度慢 4-7 倍(见基准测试:唤醒 0.92s vs 冷启动 3.72s)
  • 使用睡眠模式: 进程保持存活 → 预热投入得到回报
    • ✅ 初始预热后,分配器、计算图、进程状态和 JIT 算子全部保留
    • 结果: 首次推理保持高速(约 1s),避免了 3-4s 的冷启动惩罚

说明

耗时因模型大小、GPU 代际和配置而异。请参阅预热的影响章节,查看显示无预热时 5-7 倍减速的详细测量数据。

模型切换性能

睡眠模式最显著的优势在于模型切换时间。唤醒一个休眠模型比加载一个新的 vLLM 实例快 18-20 倍

模型切换时间:睡眠唤醒 vs 冷启动(全新加载)。
误差线显示了多次运行中的最小/最大变化。数值显示在柱状图上。
GPU: A100 | vLLM 0.11.0 | 睡眠级别: 1 | 编译设置: cudagraph_mode: FULL_AND_PIECEWISE

硬件可扩展性:A4000 GPU 结果

睡眠模式的好处不限于高端 GPU。以下是在 A4000 GPU 上运行较小模型的工作负载,证明了性能提升可以跨越不同的硬件层级和模型规模。

模型 A: Qwen3-0.6B | 模型 B: Phi-3-vision-128k-instruct
GPU: A4000 (TP=1) | vLLM 0.11.0 | 睡眠级别: 1 | 编译设置: cudagraph_mode: FULL_AND_PIECEWISE

A4000:推理性能

A4000 上的推理时间对比:唤醒模式(已预热)vs 冷启动(刚加载)。
推理时间 = Prefill + Decode(唤醒/加载后的第一条请求)。 每个请求使用不同的问题以避免缓存影响,输出限制为 100 个 token。
误差线显示了多次运行中的最小/最大变化。数值显示在柱状图上。
GPU: A4000 (TP=1) | vLLM 0.11.0 | 睡眠级别: 1 | 编译设置: cudagraph_mode: FULL_AND_PIECEWISE

A4000:模型切换性能

A4000 上的模型切换时间:睡眠唤醒 vs 冷启动(全新加载)。
误差线显示了多次运行中的最小/最大变化。数值显示在柱状图上。
GPU: A4000 (TP=1) | vLLM 0.11.0 | 睡眠级别: 1 | 编译设置: cudagraph_mode: FULL_AND_PIECEWISE

A4000 上的关键观察

  • 推理性能: 唤醒模式使 Qwen3-0.6B 的推理速度提升 83%,Phi-3-vision 提升 81%
  • 模型切换: 唤醒时间极快(约 0.1-0.8s),相比冷启动实现了 58-203 倍的加速
  • 总时间节省:62%(5 次模型切换耗时 85s vs 226s)
  • 近乎即时的切换: 对于小模型(0.1s 唤醒时间),使多模型服务感觉无缝顺滑
  • 证明了睡眠模式在不同 GPU 类别和模型规模下均有效

睡眠级别:选择合适的模式

vLLM 睡眠模式提供两个级别,具有不同的权衡:

级别 1 (默认): 将模型权重卸载到 CPU 内存,丢弃 KV 缓存

  • 唤醒时间最快(小模型约 0.1-0.8s,大模型约 3-6s)
  • 需要足够的 CPU RAM 来存储模型权重
  • 最适用于: CPU 内存充足、模型切换频繁的系统

级别 2: 丢弃模型权重和 KV 缓存,仅在 CPU 中保留缓冲区(rope scaling tensors 等)

  • 唤醒时间较慢(小模型约 0.8-2.6s),因为需要从磁盘重新加载权重
  • CPU RAM 占用极低 —— 仅保留极小的缓冲区
  • 最适用于: CPU RAM 有限,或管理许多无法全部装入内存的模型时

性能对比:级别 1 vs 级别 2 vs 无睡眠

模型 A: Qwen3-0.6B | 模型 B: Phi-3-vision-128k-instruct
GPU: A100 (TP=1) | vLLM 0.11.0 | 编译设置: cudagraph_mode: FULL_AND_PIECEWISE
对比三种模式:级别 1(最快)、级别 2(最低 RAM)、无睡眠。悬停可查看精确耗时。

性能总结

模式 总时间 唤醒时间 (A/B) CPU RAM 需求 最适合场景
无睡眠 357.1s 不适用(完整重载) 极低 单一模型,无需切换
级别 1 112.6s 0.26s / 0.82s 高(每个模型数 GB) 频繁切换,RAM 充足
级别 2 124.6s 0.85s / 2.58s 极低(每个模型数 MB) RAM 有限,成本优化

关键见解

  • 级别 1 最快(比无睡眠快 68%),但需要大量 CPU RAM
  • 级别 2 几乎同样快(比无睡眠快 65%),且对 RAM 需求极低
  • 级别 2 唤醒比级别 1 慢约 3 倍(Qwen3-0.6B 为 0.85s vs 0.26s),原因是需要重载权重
  • 两种睡眠模式都比无睡眠模式带来了巨大的提升

为什么级别 2 仍然比无睡眠模式快得多?

乍一看这似乎违反直觉:级别 2 也要从 SSD 重新加载权重(就像“无睡眠模式”一样),那为什么它总体上能快 23-45 倍?

答案是:权重加载只是五项成本中的一项

当你不在睡眠模式下重载模型时,你必须支付所有这些成本:

成本项 级别 2 无睡眠模式
1. 权重加载 (SSD → VRAM) ❌ 必须支付 ❌ 必须支付
2. 进程初始化 跳过 ❌ 必须支付
3. 内存分配器设置 跳过 ❌ 必须支付
4. CUDA 图捕获 跳过 ❌ 必须支付
5. GPU 算子 JIT 编译 已保留(已编译) ❌ 完整编译 + 预热

级别 2 策略

  • 从 SSD 重新加载权重(与无睡眠相同)
  • 其他所有内容均保留: 进程状态、分配器实例、CUDA 图和已编译的 JIT 算子全部完好无损
  • 无需重新编译: 算子在初始预热期间已编译并保持缓存状态
  • 平均每次切换:约 2.6s(见上方基准数据)

无睡眠模式现状

  • 从 SSD 重新加载权重(与级别 2 相同)
  • 所有内容重新构建: 进程重启 + 分配器初始化 + 图重新捕获
  • JIT 算子: 完整编译 + 显式预热流程(kernel_warmup() + 空运行)
  • 平均每次切换:约 48s(见上方基准数据)

基准测试数据证明了这一点: 对于 5 次模型切换

  • 级别 2: 总计 124.6s(平均每次切换约 2.6s)
  • 无睡眠: 总计 357.1s(平均每次切换约 48s)

尽管两者都要从 SSD 加载权重,但级别 2 总体快 2.9 倍,因为它保留了无睡眠模式每次都必须从头构建的昂贵基础设施(进程状态、分配器、CUDA 图)。

级别 2:推理性能

睡眠级别 2 的推理时间对比:唤醒模式 vs 冷启动。
推理时间 = Prefill + Decode(唤醒/加载后的第一条请求)。 每个请求使用不同的问题以避免缓存影响,输出限制为 100 个 token。
误差线显示了多次运行中的最小/最大变化。数值显示在柱状图上。
GPU: A100 (TP=1) | vLLM 0.11.0 | 睡眠级别: 2 | 编译设置: cudagraph_mode: FULL_AND_PIECEWISE

级别 2:模型切换性能

睡眠级别 2 的模型切换时间:睡眠唤醒 vs 冷启动。
误差线显示了多次运行中的最小/最大变化。数值显示在柱状图上。
GPU: A100 (TP=1) | vLLM 0.11.0 | 睡眠级别: 2 | 编译设置: cudagraph_mode: FULL_AND_PIECEWISE

关键观察

指标 无睡眠 级别 2 改进项
总时间 (5 次切换) 357.1s 124.6s 快 65%
Qwen3-0.6B 切换时间 平均 37.6s 平均 0.85s 快 45 倍
Phi-3-vision 切换时间 平均 58.1s 平均 2.58s 快 23 倍
Qwen3-0.6B 推理 平均 3.67s 平均 0.53s 快 86%
Phi-3-vision 推理 平均 6.30s 平均 0.76s 快 88%
唤醒时间 vs 级别 1 - 慢 3-10 倍 用速度换取 CPU RAM 节省

何时使用级别 2

  • CPU RAM 有限: 系统无法在 CPU 内存中容纳所有模型权重
  • 成本优化: 使用更便宜、CPU RAM 更少的云实例
  • 管理大量模型: 在多个模型之间切换,CPU 内存成为瓶颈
  • 依然有显著提升: 即使有权重重载,级别 2 仍比无睡眠模式快 23-45 倍

级别 1 vs 级别 2 对比

  • 级别 1:约 0.1-0.8s 唤醒时间,每个模型需要约 10-100GB+ 的 CPU RAM
  • 级别 2:约 0.8-2.6s 唤醒时间,每个模型仅需要约数 MB 的 CPU RAM
  • 两者都显著快于完整重载(约 20-100s)

消融研究

预热 (Warm-Up) 对睡眠模式的影响

跳过预热阶段会影响性能吗?预热会在初始加载期间预编译 CUDA 图,这可能需要几秒钟。让我们对比一下有无预热的情况。

模型 A: Qwen3-0.6B | 模型 B: Phi-3-vision-128k-instruct
GPU: A100 (TP=1) | vLLM 0.11.0 | 睡眠级别: 1 | 编译设置: cudagraph_mode: FULL_AND_PIECEWISE
有预热(预编译)vs 无预热(延迟编译)的对比。悬停查看精确耗时。

关键发现

指标 有预热 无预热 差异
初始加载时间 108.7s (含 8.4s 预热) 101.1s (无预热) 初始节省 7.6s
首次推理 (A) 0.45s 2.59s 无预热时慢 5.8 倍
首次推理 (B) 0.93s 6.61s 无预热时慢 7.1 倍
后续推理 平均 0.43s 平均 0.41s 无差异
总时间 (5 次切换) 119.5s 119.0s 几乎相同

见解

  • 预热编译一次,惠及所有唤醒周期: 有了初始预热,JIT 编译和 CUDA 图捕获在加载时发生一次,并在后续所有休眠/唤醒周期中保留。
  • 无预热,每次唤醒都要付编译费: 5-7 倍的减速发生在每一次唤醒后的首次推理,而不止是一次。
  • 已编译算子跨休眠/唤醒保留: 在初始加载(8.4s)预热后,所有后续唤醒的首次推理都很快(0.45s, 0.93s),证明算子保持在缓存中。
  • 极简预热即可: 单个 1-token 的推理就足以触发完整的 JIT 编译和 CUDA 图捕获,使预热成本非常低。
  • 牺牲初始加载时间换取一致的性能: 8.4s 的预热成本支付一次,平摊到所有模型切换中。
  • 建议:对于生产工作负载,始终使用预热,以确保一致且快速的推理。

量化对睡眠模式的影响

量化 (FP8) 会影响睡眠模式的性能吗?我们在 A100 GPU 上测试了开启和关闭 FP8 量化的相同工作负载。

模型 A: Qwen3-0.6B | 模型 B: Phi-3-vision-128k-instruct
GPU: A100 (TP=1) | vLLM 0.11.0 | 睡眠级别: 1 | 编译设置: cudagraph_mode: FULL_AND_PIECEWISE
BF16(基准)vs FP8 量化对比。悬停查看精确耗时。

消融:推理性能 (BF16 vs FP8)

推理时间对比:睡眠模式下的 BF16 vs FP8 量化。
推理时间 = Prefill + Decode(唤醒/加载后的第一条请求)。 每个请求使用不同的问题以避免缓存影响,输出限制为 100 个 token。
误差线显示了多次运行中的最小/最大变化。数值显示在柱状图上。
GPU: A100 (TP=1) | vLLM 0.11.0 | 睡眠级别: 1 | 编译设置: cudagraph_mode: FULL_AND_PIECEWISE

消融:模型切换 (BF16 vs FP8)

模型切换时间对比:睡眠模式下的 BF16 vs FP8 量化。
误差线显示了多次运行中的最小/最大变化。数值显示在柱状图上。
GPU: A100 (TP=1) | vLLM 0.11.0 | 睡眠级别: 1 | 编译设置: cudagraph_mode: FULL_AND_PIECEWISE

关键发现

指标 BF16 FP8 改进项
总时间 (5 次切换) 108.2s 113.6s -5% (略慢)
Qwen3-0.6B 唤醒时间 平均 0.27s 平均 0.18s 快 33%
Phi-3-vision 唤醒时间 平均 0.90s 平均 0.78s 快 13%
Qwen3-0.6B 推理 平均 0.41s 平均 0.44s -7% (略慢)
Phi-3-vision 推理 平均 0.81s 平均 0.57s 快 30%
初始加载时间 90.5s 96.9s -7% (预热更长)

见解

  • FP8 的唤醒操作更快(快 13-33%),因为涉及的内存移动更少
  • FP8 提高了大模型的推理速度(Phi-3-vision 快 30%),但对极小模型影响不大
  • FP8 的初始加载时间更长,因为预热期间有量化开销
  • 初始加载后,FP8 提供了更平滑的切换和更快的唤醒周期
  • 对于切换频繁的工作负载,FP8 更快的唤醒时间可以抵消更长的初始加载时间

决策指南:该使用哪种睡眠级别?

在以下情况下使用睡眠级别 1:

  • 你有足够的 CPU RAM 来容纳所有模型权重
  • 你需要极速唤醒时间(0.1-6s)
  • 你正在非常频繁地切换模型(每隔几秒/几分钟)
  • 推理延迟的一致性至关重要

在以下情况下使用睡眠级别 2:

  • CPU RAM 有限(无法容纳所有权重)
  • 你正在优化云成本(使用 RAM 较少的廉价实例)
  • 你有许多模型需要管理(10 个以上)

在以下情况下跳过睡眠模式:

  • 你只使用单一模型(无需切换)
  • 模型切换极少发生(每天/每周一次)
  • 两个模型可以同时装入 GPU 显存

结论

vLLM 睡眠模式将多模型 GPU 服务从 30-100 秒的重载惩罚转化为亚秒级的切换。基准测试数据说明了一切:

  • 模型切换速度提升 18-200 倍(取决于模型规模和硬件)
  • 预热模型推理速度比冷启动快 61-88%
  • 在完整工作负载中实现 65-68% 的总时间节省
  • 适用于各种规模: 从 0.6B 到 235B 参数,涵盖各种型号的 GPU

LLM 服务的未来是多模型的。睡眠模式让这一切在今天变得切实可行。

致谢

特别感谢 Vensen MuJeff AwJun Kang ChowTun Jian TanPin Siang TanAmir BalwelYe Hur CheongZhiyao CenKaichao You 开发了睡眠模式功能并撰写本博文。