vLLM V1: A Major Upgrade to vLLM's Core Architecture
vLLM V1: A Major Upgrade to vLLM's Core Architecture
发表时间: 2025-01 · Blog post by vLLM Team (blog.vllm.ai)
原文: https://blog.vllm.ai/blog/2025-01-27-v1-alpha-release
作者/机构:vLLM Team
速读
一句话结论 vLLM 团队推出了核心架构全面升级的 vLLM V1 引擎,通过重构调度器、执行循环和多模态处理机制大幅降低了 CPU 开销,在保持原有 API 不变的前提下,使文本和视觉语言模型的推理吞吐量提升了最高 1.7 倍。
要解决什么问题 原有 vLLM V0 架构在长期横向功能扩展后积累了技术债务,导致各项独立开发的优化技术难以高效垂直整合,而最致命的卡点在于日益严重的 CPU 开销瓶颈。随着 GPU 算力的提升,例如在 NVIDIA H100 上运行 Llama-8B 模型时,GPU 执行时间已降至约 5 毫秒,原本由 CPU 负责的 API 服务运行、请求调度、输入数据准备、分词与反分词以及响应流式传输等任务,占用了过多的时间比例,导致 GPU 经常处于饥饿等待状态。此外,原有架构在多个具体机制上存在效率缺陷:前缀缓存功能在缓存命中率低时会产生极大的 CPU 额外开销,导致性能不升反降;张量并行推理时,调度器与零号工作节点被放置在同一进程中,这种非对称架构增加了跨进程广播输入数据的通信开销;在每一推理步中,模型输入张量和元数据都需要被重新创建;而在处理多模态大语言模型时,图像的像素转换、裁剪等预处理工作会直接阻塞 GPU 工作节点,且文本与图像输入必须在同一步骤内处理完毕,因为视觉特征在单步执行后就会被丢弃。这些机制层面的卡点共同限制了推理引擎的并发上限与执行效率。
怎么做的 vLLM V1 的核心思路是通过彻底的架构解耦和状态缓存机制,将 CPU 密集型任务与 GPU 执行流完全剥离,并最大程度减少每步推理时的冗余计算与进程间通信。该架构由几个关键设计构成。首先是优化的执行循环与 API 服务器,V1 将多进程架构深度集成到异步引擎核心中,创建了一个隔离的 EngineCore 执行循环,专门负责调度和模型执行,从而让分词、多模态输入处理和请求流式传输等 CPU 密集型任务能在独立进程中与模型核心执行流完全重叠。其次是极简的统一调度器,它打破了传统的预填充与解码阶段的严格界限,将用户提示词和模型生成的词元一视同仁,调度决策被简化为映射关系 $ \{request\_id: num\_tokens\} $,即每步为每个请求分配要处理的词元数,这天然支持了分块预填充机制。第三是零开销的前缀缓存,通过优化数据结构实现常数时间的缓存驱逐,并严格限制 Python 对象的创建,使前缀缓存即使在零命中率下也几乎不掉速,从而得以默认开启。第四是干净的张量并行架构,V1 在工作节点端缓存了请求状态,调度器每步只向节点发送增量更新数据,这极大降低了跨进程通信开销,使得调度器和零号工作节点可以分离在不同进程中,形成对称架构。第五是高效的输入准备,引入了持久化批处理技术,缓存输入张量并主要使用 Numpy 操作替代原生 Python 操作来应用增量更新。第六是针对多模态模型的原生增强,将图像预处理卸载到非阻塞独立进程并引入预处理缓存,同时利用图像哈希值实现了多模态前缀缓存;更关键的是引入了编码器缓存机制,临时保存视觉特征,使得多模态请求也能进行分块预填充,打破了图文必须同步骤处理的限制。最后,系统集成了 torch.compile、分段 CUDA 图以及 FlashAttention 3,以支持在同一批次中动态混合预填充与解码任务。
效果如何 实验在 NVIDIA GPU 硬件环境下进行,对比基线为上一代引擎 vLLM V0,代表未经过 CPU 开销深度优化的传统异步推理路线。在纯文本模型测试中,使用 ShareGPT 数据集对 Llama 3.1 8B 和 Llama 3.3 70B 模型进行评估,结果显示在未使用多步调度的情况下,V1 实现了最高 1.7 倍的吞吐量提升,且在高并发请求率下展现出更低的延迟。在视觉语言模型测试中,使用 VisionArena 数据集对 Qwen2-VL 模型进行评估,得益于独立的预处理进程和更灵活的多模态调度机制,V1 相比 V0 获得了比纯文本模型更显著的加速比。此外,消融测试表明 V1 的前缀缓存机制在零命中率时的吞吐量下降不到 1%。不过作者也坦承了当前 Alpha 版本的局限性:在模型支持上,目前仅支持仅解码器架构和混合专家模型,暂不支持多模态 Llama 3.2 等编码器-解码器架构、Mamba 架构或嵌入模型;在功能上,暂时缺失对数概率输出、流水线并行、结构化解码、投机解码和 LoRA 的支持;在硬件上,目前仅支持 Ampere 及更新架构的 NVIDIA GPU,尚未支持 TPU 等其他硬件后端。
主要贡献
vLLM团队正式发布了vLLM V1的Alpha版本,这是对vLLM核心架构的一次重大升级。在过去一年半的开发中,随着vLLM在横向扩展(支持多种模型、特性和硬件后端)上取得巨大成功,系统内部积累了较多技术债务,独立开发的特性难以在垂直技术栈上实现干净、高效的融合。
为了解决这一问题,研究团队重新审视了关键的设计决策,对核心组件进行了全面的重构。vLLM V1的核心目标是提供一个简单、模块化且易于二次开发的代码库,同时确保极高的性能(接近零的CPU开销)。V1通过统一的架构整合了关键的优化技术,并实现了“零配置”——默认开启各项优化特性。用户无需修改现有的API,只需设置环境变量VLLM_USE_V1=1即可无缝切换到V1引擎。目前,V1已经实现了业界领先(state-of-the-art)的性能表现,并为未来的进一步优化奠定了基础。
背景知识与设计原则
从vLLM V0中吸取的教训
在过去的1.5年中,vLLM在支持多样化模型、功能和硬件后端方面取得了显著的成功。然而,随着社区的横向扩展,系统面临着保持简洁性以及在整个技术栈中垂直集成各种优化的挑战。由于许多功能通常是独立开发的,导致很难将它们有效且干净地结合在一起。随着时间的推移,技术债务不断积累,这促使团队重新审视其基础架构设计。
V1的设计目标
基于上述动机,vLLM V1的设计旨在实现以下四个核心目标:
- 提供一个简单、模块化且易于修改(easy-to-hack)的代码库。
- 确保高性能,实现接近零的CPU开销。
- 将各项关键优化技术结合到一个统一的架构中。
- 要求零配置,通过默认启用各项功能和优化来简化用户使用。
V1的重构范围
vLLM V1对其核心组件引入了全面的重新架构,涵盖了调度器(scheduler)、KV缓存管理器(KV cache manager)、工作节点(worker)、采样器(sampler)以及API服务器(API server)。尽管进行了深度重构,V1仍然与vLLM V0共享了大量代码,例如模型实现代码、GPU算子(kernels)、分布式控制平面以及各种实用工具函数。这种策略使得V1能够充分利用V0已经建立的广泛覆盖率和系统稳定性,同时在性能和降低代码复杂度方面交付显著的提升。
核心方法细节
优化的执行循环与API服务器
作为一个功能完备的连续批处理(continuous batching)引擎和兼容OpenAI格式的API服务器,vLLM的核心执行循环依赖于CPU操作来管理模型前向传播(forward passes)之间的请求状态。随着GPU计算速度的提升并大幅减少模型执行时间,诸如运行API服务器、调度任务、准备输入数据、对输出进行反词元化(de-tokenizing)以及向用户流式传输响应等任务所带来的CPU开销变得越来越明显。这一问题在NVIDIA H100 GPU上运行Llama-8B等较小模型时尤为突出,其在GPU上的单次执行时间已低至约5毫秒。
在v0.6.0版本中,vLLM引入了利用ZeroMQ进行进程间通信(IPC)的多进程API服务器,从而实现了API服务器与AsyncLLM之间的重叠执行。vLLM V1进一步扩展了这一理念,将多进程架构更深地集成到AsyncLLM的核心中,创建了一个隔离的EngineCore执行循环。该循环专门专注于调度器和模型执行器的工作。这种设计允许诸如词元化(tokenization)、多模态输入处理、反词元化以及请求流式传输等CPU密集型任务与核心GPU执行循环产生更大程度的重叠,从而最大化模型的吞吐量。
简单且灵活的调度器
vLLM V1引入了一个既简单又灵活的调度器。该调度器消除了传统意义上“预填充(prefill)”和“解码(decode)”阶段的区分,将用户提供的提示词词元(prompt tokens)和模型生成的输出词元(output tokens)一视同仁地进行处理。
在具体实现上,调度决策被表示为一个简单的字典结构,例如 {request_id: num_tokens}。该字典明确指定了在每一个计算步骤中,需要为每个请求处理的词元数量。研究团队发现,这种表示方法具有足够的通用性,能够原生支持分块预填充(chunked prefills)、前缀缓存(prefix caching)以及投机解码(speculative decoding)等高级特性。例如,分块预填充调度的实现变得无缝衔接:在固定的词元预算下,调度器可以动态决定分配给每个请求的词元数量。
零开销的前缀缓存
与V0一样,vLLM V1使用了基于哈希(hash-based)的前缀缓存和基于最近最少使用(LRU)原则的缓存驱逐策略。在V0版本中,启用前缀缓存有时会引发显著的CPU开销,导致在缓存命中率较低时性能反而下降,因此该功能在V0中默认是关闭的。
在V1中,团队优化了底层数据结构以实现常数时间(constant-time)的缓存驱逐,并极其谨慎地最小化了Python对象创建时的开销。这些优化使得V1的前缀缓存引入了接近零的性能衰减。基准测试结果表明,即使在缓存命中率为$0\%$的极端情况下,V1的前缀缓存导致的吞吐量下降也小于$1\%$;而在缓存命中率较高时,它能将性能提升数倍。得益于这种极低的开销,前缀缓存现在在V1中被默认开启。
用于张量并行推理的清晰架构
vLLM V1引入了一种干净且高效的张量并行(tensor-parallel)推理架构,有效解决了V0架构的局限性。在V0中,调度器和Worker 0被部署在同一个进程中,其目的是为了减少向各个worker广播输入数据时的进程间通信开销。然而,这种设计导致了非对称的架构,增加了系统的复杂性。
V1通过在worker端缓存请求状态,并在每个步骤中仅传输增量更新(diffs)来克服这一问题。这种优化极大地最小化了进程间通信量,允许调度器和Worker 0在完全独立的进程中运行,从而形成了一个干净、对称的架构。此外,V1抽象并隐藏了大部分分布式逻辑,使得worker在单GPU和多GPU环境下的运行方式保持完全一致。
高效的输入准备
在vLLM V0中,模型的输入张量和元数据在每个步骤中都会被重新创建,这通常会导致显著的CPU开销。为了优化这一过程,V1实现了Persistent Batch(持久化批处理)技术(该技术借鉴自LMDeploy)。该技术会缓存输入张量,并在每个步骤中仅对它们应用增量修改(diffs)。
此外,在更新张量的过程中,V1广泛使用了Numpy操作来替代Python的原生操作,从而进一步最小化了更新张量时的CPU开销。
torch.compile与分段CUDA图
V1深度利用了vLLM的torch.compile集成功能来自动优化模型。这使得V1能够高效地支持种类繁多的模型,同时最大限度地减少了编写自定义CUDA算子的需求。此外,V1引入了分段CUDA图(piecewise CUDA graphs)技术,以缓解传统CUDA图机制带来的局限性。
增强的多模态LLM支持
vLLM V1将多模态大型语言模型(MLLMs)视为一等公民,并在其支持上引入了几个关键的改进:
- 非阻塞的输入预处理:V1通过将多模态输入预处理转移到非阻塞进程中来进行优化。例如,图像文件(如JPG或PNG)在输入模型之前,必须被转换为像素值张量、进行裁剪和变换。这种预处理会消耗大量的CPU周期,可能导致GPU处于空闲状态。V1将预处理任务卸载到独立的进程中,防止其阻塞GPU worker,并增加了一个预处理缓存(preprocessing cache),以便如果多个请求共享相同的多模态输入,已处理的输入可以被复用。
- 多模态前缀缓存:V1引入了针对多模态输入的前缀缓存。除了词元ID的哈希值外,图像的哈希值也被用来标识图像输入的KV缓存。这一改进对于包含图像输入的多轮对话场景尤为有利。
- 基于“编码器缓存”的MLLM分块预填充调度:在V0中,由于LLM解码器的词元依赖于视觉嵌入(vision embeddings),而这些嵌入在单步执行后就会被丢弃,因此图像输入和文本输入必须在同一步骤中处理。V1通过引入“编码器缓存(encoder cache)”临时存储视觉嵌入,允许调度器将文本输入拆分成多个块(chunks),并在多个步骤中跨步处理它们,而无需在每个步骤重新生成视觉嵌入。
FlashAttention 3的集成
vLLM V1架构拼图的最后一块是集成了FlashAttention 3。考虑到V1中极高的动态性——例如在同一个批次(batch)中混合预填充和解码任务——一个灵活且高性能的注意力机制算子是必不可少的。FlashAttention 3有效地满足了这一需求,不仅为各种特性提供了强大的支持,还在多样化的用例中保持了卓越的性能。
实验环境
-
测试模型:
- 文本模型:Llama 3.1 8B, Llama 3.3 70B
- 视觉语言模型(VLMs):Qwen2-VL
-
测试数据集:
- 文本模型评估使用 ShareGPT 数据集。
- 视觉语言模型评估使用 VisionArena 数据集。
-
硬件配置:NVIDIA GPU(文中明确提及了Llama-8B在H100上的运行情况;V1当前支持Ampere或更新架构的NVIDIA GPU)。
- 软件配置:vLLM V0 与 vLLM V1 (Alpha版本) 对比,启用了
torch.compile与 FlashAttention 3。
实验结果
得益于广泛的架构增强,vLLM V1实现了业界领先的吞吐量和延迟表现。在不使用多步调度(multi-step scheduling)的情况下,V1相比V0提供了高达1.7倍的吞吐量提升。这些巨大的性能收益源于整个技术栈中CPU开销的全面降低。由于V1对视觉语言模型(VLMs)如Qwen2-VL的支持得到了增强,其在多模态模型上的性能提升更为显著。
文本模型性能:Llama 3.1 8B & Llama 3.3 70B
研究团队使用ShareGPT数据集对Llama 3.1 8B和Llama 3.3 70B模型进行了性能测量。结果显示,V1的延迟始终低于V0,尤其是在高QPS(每秒查询率)的情况下,这得益于其实现了更高的吞吐量。鉴于V0和V1使用的底层算子几乎完全相同,这种性能差异主要归功于V1在架构上的改进(即CPU开销的减少)。
视觉语言模型性能:Qwen2-VL
团队使用VisionArena数据集测试了Qwen2-VL,以评估V1在VLM上的性能。得益于改进的VLM支持,V1相较于V0实现了更大的加速比。这主要由两项关键改进驱动:将输入处理卸载到独立进程中,以及为多模态查询实现了更灵活的调度机制。此外,V1现在对多模态模型原生支持前缀缓存(该特性的具体基准测试结果在此处略过)。
结论与未来工作
vLLM V1通过重新设计的架构提供了坚实的基础,将加速未来新功能的开发。尽管V1展现了极具前景的测试结果,但它目前仍处于Alpha阶段,且缺少V0中的部分功能。
模型支持限制:
V1目前支持仅解码器(decoder-only)的Transformer模型(如Llama)、混合专家(MoE)模型(如Mixtral)以及部分VLM(如Qwen2-VL),并支持所有量化方法。但是,V1当前不支持编码器-解码器架构(如多模态Llama 3.2)、基于Mamba的模型(如Jamba)以及嵌入(embedding)模型。
功能限制:
V1目前缺乏对对数概率(log probs)、提示词对数概率采样参数、流水线并行(pipeline parallelism)、结构化解码(structured decoding)、投机解码(speculative decoding)、Prometheus指标以及LoRA的支持。团队正在积极弥补这些功能差距,并计划为V1引擎添加全新的优化。
硬件支持限制:
V1目前仅支持Ampere或更新版本的NVIDIA GPU。团队正在积极致力于将支持扩展到其他硬件后端,例如TPU。
最后,用户如果不想切换,可以通过不设置 VLLM_USE_V1=1 继续使用V0版本,以保持向后兼容性。
附录
原文无附录内容。
补充细节
如何开始使用
- 通过命令
pip install vllm --upgrade安装最新版本的vLLM。 - 设置环境变量
export VLLM_USE_V1=1。 - 使用vLLM的Python API或兼容OpenAI的服务器(
vllm serve <model-name>)。用户无需对现有的API代码进行任何修改。
致谢与开发背景
vLLM V1的设计建立在多个开源LLM推理引擎的基础之上并对其进行了增强,这些引擎包括LightLLM、LMDeploy、SGLang、TGI以及TRT-LLM。研究团队从这些项目中获得了宝贵的见解。
V1的重构是整个vLLM团队和社区持续共同努力的结果,主要由加州大学伯克利分校(UC Berkeley)、Neural Magic(现属于Red Hat)、Anyscale和Roblox共同推动。核心贡献细节包括:
- Woosuk Kwon 发起了该项目,并实现了调度器和模型运行器。
- Robert Shaw 实现了优化的执行循环和API服务器。
- Cody Yu 实现了针对文本和图像输入的高效前缀缓存。
- Roger Wang 领导了V1中整体增强的MLLM支持。
- Kaichao You 领导了
torch.compile的集成,并实现了分段CUDA图。 - Tyler Michael Smith 使用Python多进程实现了张量并行支持。
- Rui Qiao 使用Ray实现了张量并行支持,并正在实现流水线并行。
- Lucas Wilkinson 添加了对FlashAttention 3的支持。
- Alexander Matveev 实现了优化的多模态输入预处理器,并正在实现TPU支持。
- Sourashis Roy 在采样器中实现了logit惩罚机制。
- Cyrus Leung 领导了MLLM输入处理的重构,并协助其集成到V1中。
- Russell Bryant 解决了多个与多进程相关的问题。
- Nick Hill 优化了引擎循环和API服务器。
- Ricky Xu 和 Chen Zhang 协助重构了KV缓存管理器。
- Jie Li 和 Michael Goin 协助了MLLM的支持与优化。
- Aaron Pham 正在实现结构化解码支持。
- Varun Sundar Rabindranath 正在实现多LoRA支持。
- Andrew Feldman 正在实现对数概率和提示词对数概率的支持。
- Lily Liu 正在实现投机解码支持。
- Kuntai Du 正在实现预填充解耦(prefill disaggregation)和KV缓存传输支持。
- Simon Mo 和 Zhuohan Li 对V1的系统设计做出了贡献。
💬 评论讨论
欢迎在这里分享您的想法和见解!