引言

多模型服务的难题: 您有两个大语言模型(LLM),每个都能单独放入您的 GPU,但无法同时容纳。传统解决方案迫使您做出糟糕的权衡:

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

vLLM Sleep Mode

vLLM 睡眠模式提供了第三种方式: 模型可在数秒内休眠并快速唤醒——实现了按需加载的效率与持久化服务的速度。

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

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

两种级别都比完全重载快 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 vs 无睡眠模式的性能

下面的交互式图表显示了执行 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

推理性能提升

除了更快的模型切换,睡眠模式还提供更快的推理时间。因为模型从睡眠中唤醒时已经预热过,它们跳过了新加载模型会遇到的冷启动开销。

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

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

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

睡眠模式保留了什么

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

关键区别

  • 不使用睡眠模式: 进程在卸载时终止 → 您无法从预热中受益
    • 必须重启 Python 进程和 CUDA 上下文
    • 必须重新初始化内存分配器
    • 必须重新捕获 CUDA 图
    • 必须重新 JIT 编译内核(DeepGEMM、FlashInfer、TorchInductor)
    • 结果: 首次推理速度慢 4-7 倍(参见基准测试:0.92 秒唤醒 vs 3.72 秒冷启动)
  • 使用睡眠模式: 进程保持存活 → 预热效果显著
    • ✅ 分配器、图、进程状态和 JIT 内核在初次预热后都得到保留
    • 结果: 首次推理保持快速(约 1 秒),避免了 3-4 秒的冷启动惩罚

说明

时间因模型大小、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.8 秒),与冷启动相比实现了 58-203 倍的加速
  • 总时间节省:62%(5 次模型切换,85 秒 vs 226 秒)
  • 小型模型的近乎即时切换(0.1 秒唤醒时间),使多模型服务感觉无缝
  • 证明了睡眠模式在不同 GPU 等级和模型大小上均有效

睡眠级别:选择正确的模式

vLLM 睡眠模式提供两种级别,各有不同的权衡

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

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

级别 2: 丢弃模型权重和 KV 缓存,仅在 CPU 中保留缓冲区(如 rope 缩放张量等)

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

性能比较:级别 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(内存占用最小)、无睡眠。悬停查看确切时间。

性能总结

模式 总时间 唤醒时间 (A/B) CPU 内存 最适合
无睡眠 357.1 秒 N/A(完全重载) 最小 单一模型,无需切换
级别 1 112.6 秒 0.26 秒 / 0.82 秒 高(每个模型约 GB) 切换频繁,内存充足
级别 2 124.6 秒 0.85 秒 / 2.58 秒 最小(每个模型约 MB) 内存有限,成本优化

关键见解

  • 级别 1 最快(比无睡眠快 68%),但需要大量 CPU 内存
  • 级别 2 几乎同样快(比无睡眠快 65%),且内存需求极小
  • 级别 2 唤醒比级别 1 慢约 3 倍(Qwen3-0.6B 为 0.85 秒 vs 0.26 秒),因为需要重载权重
  • 两种睡眠模式都比无睡眠模式有巨大改进

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

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

答案:权重加载只是五个成本之一

当您在不使用睡眠模式的情况下重新加载模型时,您需要支付所有这些成本:

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

级别 2 策略

  • 从 SSD 重载权重(与无睡眠模式相同)
  • 其他一切都保留: 进程状态、分配器实例、CUDA 图和已编译的 JIT 内核都完好无损
  • 无需重新编译: 内核在初次预热期间已编译并保持缓存
  • 每次切换平均耗时:约 2.6 秒(见上文基准数据)

无睡眠模式的现实

  • 从 SSD 重载权重(与级别 2 相同)
  • 其他一切都重建: 进程重启 + 分配器初始化 + 图重新捕获
  • JIT 内核: 完全编译 + 显式预热程序 (kernel_warmup() + 虚拟运行)
  • 每次切换平均耗时:约 48 秒(见上文基准数据)

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

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

尽管两者都从 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.1 秒 124.6 秒 快 65%
Qwen3-0.6B 切换时间 平均 37.6 秒 平均 0.85 秒 快 45 倍
Phi-3-vision 切换时间 平均 58.1 秒 平均 2.58 秒 快 23 倍
Qwen3-0.6B 推理 平均 3.67 秒 平均 0.53 秒 快 86%
Phi-3-vision 推理 平均 6.30 秒 平均 0.76 秒 快 88%
与级别 1 相比的唤醒时间 - 慢 3-10 倍 用 CPU 内存换取速度

何时使用级别 2

  • CPU 内存有限: 系统无法在 CPU 内存中容纳所有模型权重
  • 成本优化: 使用 CPU 内存较少的更便宜的云实例
  • 模型众多: 在多个模型间切换,且 CPU 内存是限制因素
  • 仍然有显著增益: 即使需要重载权重,级别 2 仍比无睡眠模式快 23-45 倍

级别 1 vs 级别 2 比较

  • 级别 1:约 0.1-0.8 秒唤醒时间,每个模型需要约 10-100GB+ CPU 内存
  • 级别 2:约 0.8-2.6 秒唤醒时间,每个模型仅需约 MB 级 CPU 内存
  • 两者都比完全重载(约 20-100 秒)快得多

消融研究

预热对睡眠模式的影响

跳过预热阶段会影响性能吗?预热会在初始加载期间预编译 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.7 秒(包括 8.4 秒预热) 101.1 秒(无预热) 初始节省 7.6 秒
首次推理 (A) 0.45 秒 2.59 秒 无预热慢 5.8 倍
首次推理 (B) 0.93 秒 6.61 秒 无预热慢 7.1 倍
后续推理 平均 0.43 秒 平均 0.41 秒 无差异
总时间(5 次切换) 119.5 秒 119.0 秒 几乎相同

见解

  • 预热一次编译内核,惠及所有唤醒周期: 通过初始预热,JIT 编译和 CUDA 图捕获在加载时发生一次,并在所有后续的休眠/唤醒周期中保留
  • 无预热,每次唤醒都付出编译成本: 5-7 倍的减速发生在每次唤醒后的首次推理中,而不仅仅是一次
  • 编译后的内核在休眠/唤醒中保留: 在初始加载期间预热(8.4 秒)后,所有后续唤醒的首次推理都很快(0.45 秒,0.93 秒),证明内核保持缓存
  • 最小化预热即可: 单个 1-token 的推理足以触发完整的 JIT 编译和 CUDA 图捕获,使预热成本非常低
  • 用初始加载时间换取一致的性能: 8.4 秒的预热成本支付一次,并在所有模型切换中分摊
  • 建议:对于生产工作负载,始终使用预热,以期获得一致、快速的推理性能

量化对睡眠模式的影响

量化(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.2 秒 113.6 秒 -5%(稍慢)
Qwen3-0.6B 唤醒时间 平均 0.27 秒 平均 0.18 秒 快 33%
Phi-3-vision 唤醒时间 平均 0.90 秒 平均 0.78 秒 快 13%
Qwen3-0.6B 推理 平均 0.41 秒 平均 0.44 秒 -7%(稍慢)
Phi-3-vision 推理 平均 0.81 秒 平均 0.57 秒 快 30%
初始加载时间 90.5 秒 96.9 秒 -7%(预热时间更长)

见解

  • FP8 的唤醒操作更快(快 13-33%),因为内存移动更少
  • FP8 改善了较大模型的推理性能(Phi-3-vision 快 30%),但对微小模型差异不大
  • 使用 FP8 的初始加载时间更长,因为预热期间有量化开销
  • 初始加载后,FP8 提供更平滑的切换和更快的唤醒周期
  • 对于切换频繁的工作负载,FP8 更快的唤醒时间可以抵消较长的初始加载时间

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

何时使用睡眠级别 1

  • 您有足够的 CPU 内存来容纳所有模型权重
  • 您需要尽可能快的唤醒时间(0.1-6 秒)
  • 您非常频繁地切换模型(每隔几秒/几分钟)
  • 推理延迟的一致性至关重要

何时使用睡眠级别 2

  • CPU 内存有限(无法容纳所有模型权重)
  • 您正在优化云成本(内存较少的更便宜的实例)
  • 您需要管理许多模型(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 开发了睡眠模式功能并撰写了这篇博客文章。