Model Runner V2: A Modular and Faster Core for vLLM
Model Runner V2: A Modular and Faster Core for vLLM
发表时间: 2026-03 · Blog post by vLLM Team (blog.vllm.ai)
原文: https://blog.vllm.ai/blog/2026-03-24-mrv2
作者/机构:vLLM Team (Woosuk Kwon, Nick Hill, Giancarlo Delfin, Santino Ramos, Wentao Ye, Zhanqiu Hu, Lucas Wilkinson, Haoran Zhu)
速读
一句话结论
vLLM 团队重构了其底层的模型执行器,推出了 Model Runner V2(MRV2),通过将状态管理与输入准备下沉至 GPU、原生支持异步调度以及模块化解耦,在不改变用户 API 的前提下大幅降低了 CPU 调度开销并提升了系统吞吐量。
要解决什么问题
原有 vLLM V1 版本的执行器在不断叠加新特性后,积累了严重的架构技术债,导致系统在多个机制上卡点频发。首先是持久化批处理状态(Persistent Batch State)的耦合问题,V1 将持久化状态直接用作模型和采样器的每步输入,这导致请求的插入、移除和重排操作受到严格的内存布局限制,带来了极高的状态管理复杂度。其次是 CPU 绑定的调度开销问题,输入数据的准备和采样过程依赖大量细碎的 CPU 端 Python 和张量操作,随着 GPU 算力的不断提升,这种 CPU 端的记账(Bookkeeping)工作成为了严重的性能瓶颈。再次是异步执行的脆弱性,V1 的异步调度是后期强行改造接入的,导致投机解码(Speculative Decoding)等新功能很难与异步调度干净地共存,经常需要引入复杂的同步逻辑。最后是代码扩展性极差,处理不同模型架构的逻辑全部堆砌在公共执行路径中,单个核心文件甚至膨胀到了 6700 多行,使得新模型的接入变得异常困难。
怎么做的
MRV2 的核心思路是围绕模块化、GPU 原生、异步优先三个原则彻底重写执行引擎。首先,设计了全新的持久化批处理机制与 GPU 原生的输入准备流程。MRV2 将持久化的请求状态与每步的输入张量彻底解耦。每个活跃请求在其生命周期内,会在一个固定大小的状态表中占据稳定的行。在每个推理步,执行器会根据当前的请求顺序,通过 Gather 操作从该持久化状态中收集并构建当前步的输入。这种设计保留了增量更新的性能优势,同时消除了 V1 中为了应对张量全局重排而存在的冗余备份状态。更关键的是,MRV2 使用 Triton 编写了底层算子,将 input_ids、positions、query_start_loc 和 seq_lens 等张量的构建工作全部下沉到 GPU 上完成,彻底绕开了 CPU 端的张量操作瓶颈。其次,确立了异步优先的零同步架构。MRV2 将 CPU 与 GPU 的重叠执行作为基础设计约束,目标是在所有支持的模型和特性组合下实现 CPU 与 GPU 之间的零同步。由于输入准备工作已经转移到了 GPU 端,准备算子现在可以直接消费 GPU 产生的拒绝采样(Rejection Sampling)结果。每步的输出会通过一个独立的 CUDA 流异步传输回 CPU,与主计算流完全解耦。这种机制使得异步调度与投机解码终于能够完美结合。第三,引入了原生的 Triton 采样器。为了更好地控制显存和数值精度,MRV2 重写了采样逻辑:实现了 Gumbel-Max 采样算子,避免了显式的 Softmax 计算并使用了无状态的核内随机数生成器;优化了 Top-k 的对数概率计算,先找出 Top-k 的逻辑值,只对选中的候选者计算对数概率;通过更细粒度的分块机制降低了提示词对数概率的显存峰值;并在算子内部使用索引映射(idx_mapping)来替代请求状态的全局展开,从而更好地兼容投机解码。最后,进行了强模块化重构。MRV2 引入了 ModelState 抽象接口,将多模态嵌入、额外模型输入、注意力元数据准备等模型特定的逻辑全部封装起来,使得主执行器只关注公共路径。这一改造将原本臃肿的核心文件拆分,目前最大的单文件代码量已控制在 1300 行以内。
效果如何
实验主要在极小模型和投机解码两种容易放大调度开销的设置下进行,对比的基线方法均为 vLLM 原有的 MRV1 执行器。为了极限测试主机端(CPU)的调度开销,作者在单张 GB200 硬件上运行了极小的 Qwen3-0.6B 模型。在这个设置下,由于 MRV2 将输入准备工作卸载到了 GPU,系统吞吐量从 MRV1 的 16K 输出 tokens/秒提升到了 25K 输出 tokens/秒,实现了 56% 的吞吐量增长。在投机解码的测试中,作者在 4 张 GB200 上运行了 GLM-4.7-FP8 模型,并设置投机步数 MTP=1。得益于 MRV2 的零同步设计彻底消除了开启投机解码时的 CPU-GPU 同步点,该设置下的每个输出 token 耗时(TPOT)降低了 6.3%。该方法目前的代价和局限性在于它仍处于实验性开发阶段,尚未实现全功能覆盖。作者明确指出,当前版本不支持线性注意力模型(如 Qwen3.5、Nemotron 3 Super)、除 Eagle/Eagle3/MTP 之外的其他投机解码方法、EPLB、DBO、Logits 处理器以及 LoRA 微调模块。
主要贡献
vLLM团队推出了Model Runner V2 (MRV2),这是对vLLM模型运行器(model runner)的彻底重新实现。MRV2的核心目标是通过提供一个更简洁、更模块化且更高效的执行核心来提升代码质量与性能,同时保证没有任何API的更改。
此次架构升级是基于vLLM庞大用户群和社区反馈中汲取的经验教训。研究团队重新审视了持久化批处理(persistent batching)、异步调度(async scheduling)、输入准备(input preparation)和采样(sampling)等核心机制,并围绕以下三个核心原则重建了模型运行器:
- 模块化(Be modular):将特定于模型的逻辑与公共执行路径隔离开来。
- GPU原生(Be GPU-native):将簿记(bookkeeping)工作从CPU转移到GPU上执行。
- 异步优先(Be async-first):将CPU/GPU的重叠执行视为一项设计约束,而不是事后的功能改造。
背景知识与设计原则
技术债务的积累。自去年vLLM V1发布以来,随着功能和优化的逐步增加,模型运行器积累了大量的技术债务。虽然这些更改在孤立状态下是有用的,但随着时间的推移,其实现变得越来越难以理解,特别是当异步调度和投机解码(speculative decoding)成为执行模型的核心部分时。
V1架构存在的具体问题。在实际应用中,原有的架构导致了几个反复出现的问题:
- 纠缠的持久化批处理状态(Tangled persistent batch state):持久化状态与每步的模型输入紧密耦合,这导致请求的插入、删除和重排序操作变得异常复杂。
- 脆弱的异步执行(Fragile async execution):异步调度是后来才改装到V1运行器上的,因此许多新功能需要依赖极其不自然且复杂的逻辑才能与之共存。
- 受限于CPU的簿记工作(CPU-bound bookkeeping):输入准备和采样依赖于大量小型的CPU端操作,随着GPU计算速度的不断提升,这种设计将大量性能潜力白白浪费。
- 扩展性困难(Difficult extensibility):随着新模型和新功能的不断加入,整个运行器变得难以理解,也难以进行干净利落的扩展。
MRV2的解决思路。为了应对上述挑战,MRV2通过引入更清晰的状态所有权和更明确的抽象来重新思考模型运行器的设计,从根本上解决了这些痛点。
方法细节
1. 更好的持久化批处理设计与GPU原生输入准备
V1的簿记开销与持久化批处理。vLLM在批处理、分页注意力(paged attention)、采样参数等方面执行了大量的簿记工作。历史上,其中大部分工作被实现为许多小型的CPU端操作。为了减少这种开销,vLLM V1引入了持久化批处理:由于连续的批次通常是相似的,因此增量更新缓存状态比每步从头开始重建大型张量要便宜得多。然而,V1的设计直接将持久化状态用作模型和采样的输入,这造成了尴尬的布局约束并使簿记工作复杂化。
MRV2的持久化请求状态解耦。MRV2将持久化请求状态与每步输入张量进行了解耦。每一个活跃的请求在其活跃的生命周期内,都会在一个固定大小的状态表中获得一个稳定的行。在每一步中,运行器会根据当前的请求顺序,从该持久化状态中收集(gather)特定于该步骤的输入。这一设计保留了增量更新的性能优势,同时消除了大量的状态管理复杂性。由于活跃请求不再依赖于脆弱的张量级重排序,这也消除了冗余的备份状态(例如CachedRequestState)。
GPU原生的输入准备。MRV2还利用Triton内核将输入准备工作转移到了GPU上。请求状态主要保存在设备(device)上,而诸如input_ids、positions、query_start_loc和seq_lens等张量现在直接在GPU上构建。这一改变带来了三个具体的优势:
- 降低CPU开销:通过避免大量的Python和CPU张量操作来实现。
- 降低代码复杂度:消除了由CPU端张量操作所强加的种种约束。
- 更好的异步和投机解码兼容性:因为常驻GPU的准备工作可以直接消耗设备端的结果,而无需进行CPU-GPU同步(具体见下一节)。
2. 异步优先设计
V1中的异步调度重叠。异步调度现在是vLLM的基础。调度器和工作节点在GPU执行第$N$步的同时准备第$N+1$步,通过重叠主机(host)工作和设备(device)工作来最大化利用率。虽然这在vLLM V1中已经得到支持,但它在很大程度上是一种事后改造,而不是作为一等公民的设计约束。
MRV2的零同步异步执行。MRV2将异步执行视为核心假设,其目标是在所有支持的模型和功能组合中,实现CPU和GPU之间的零同步(zero synchronization)。
异步调度与投机解码的自然结合。重要的是,MRV2自然地将异步调度和投机解码结合在一起,而这种组合在V1中很难被干净地支持。因为MRV2的输入准备运行在设备上,准备内核(prep kernels)可以直接消耗由GPU产生的拒绝采样(rejection sampling)结果。每一步的输出会在一个独立的CUDA流中异步传输到CPU,与主计算流完全解耦。这种设计同样适用于带有结构化输出的投机解码。
3. Triton原生采样器
Triton原生采样的优化。MRV2使用优化的Triton内核重构了采样模块,以便更好地控制内存使用和数值计算。具体的改进包括:
- Gumbel-Max采样内核:该内核避免了显式的softmax实例化,并在内核中使用了无状态的随机数生成器(RNG)。
- 更高效的top-k logprobs:通过首先找到top-k的对数几率(logits),并且只为选定的候选者计算logprobs,从而提升效率。
- 内存效率更高的prompt logprobs:通过更细粒度的分块(chunking)来实现,包括在单个prompt内进行分块。
- 更好的投机解码兼容性:通过在内核内部使用间接寻址(
idx_mapping),而不是扩展请求状态以匹配每个logits向量。
采样优化的效果。综合来看,这些改变降低了峰值内存使用量,并使得支持采样参数的丰富组合变得更加容易。
4. 更强的模块化
ModelState抽象的设计。vLLM需要支持广泛的模型架构,现有的模型运行器因此积累了相当大的复杂性。MRV2通过引入一个新的抽象层来解决这个问题:ModelState。
class ModelState(ABC):
def add_request(self, ...):
def remove_request(self, ...):
def get_mm_embeddings(self, ...):
def prepare_inputs(self, ...):
def prepare_attn(self, ...):
def prepare_dummy_inputs(self, ...):
...
隔离模型特定逻辑。ModelState定义了特定于模型的逻辑接口,包括多模态嵌入(multimodal embeddings)、额外的模型输入、注意力元数据(attention metadata)以及CUDA图捕获(CUDA graph capture)。这样一来,主运行器就可以专注于公共执行路径。这直接解决了用户和贡献者经常抱怨的一个问题:vLLM支持的模型太多,导致共享代码显得晦涩难懂,特别是对于那些只关注某一个模型系列(如DeepSeek、Qwen、Kimi或内部私有模型)的开发者而言。
文件结构的拆分与重组。此外,MRV2将运行器拆分为具有更清晰职责的较小文件。现有的运行器(gpu_model_runner.py)已经膨胀成一个超过6700行的单个文件;而在MRV2中,最大的文件现在也不到1300行。
实验环境与实验结果
团队对MRV2进行了压力测试,以验证其性能提升。
实验一:小模型吞吐量测试
- 实验环境:模型选用极小的
Qwen3-0.6B(故意选择小模型以放大主机端开销的比例),硬件配置为1×GB200GPU。 - 实验结果:MRV2的吞吐量达到了25K output tok/s,而MRV1为16K output tok/s,吞吐量提升了56.2%。
- 分析结论:通过将输入准备工作卸载到GPU上,MRV2显著降低了CPU开销,带来了明显的吞吐量提升。
实验二:投机解码TPOT测试
- 实验环境:模型选用
GLM-4.7-FP8,配置MTP=1,硬件配置为4×GB200GPU。 - 实验结果:在各种请求速率下,MRV2的平均每个输出Token时间(Mean TPOT)降低了6.3%。
- 分析结论:这一改进得益于MRV2的零同步设计,在启用投机解码时彻底消除了CPU-GPU同步点。
随着服务栈继续结合异步调度、投机解码、多模态预处理和日益异构的模型状态,预计这种架构基础将发挥更大的作用。
结论
当前状态与局限性:MRV2目前仍处于实验阶段并正在积极开发中。虽然设计更清晰且早期结果强劲,但尚未实现功能完备。截至v0.18.0版本,MRV2不支持以下功能:
- 线性注意力模型(如Qwen3.5, Nemotron 3 Super)
- 除Eagle/Eagle3/MTP之外的投机解码方法
- EPLB和DBO
- Logits处理器
- LoRA
开发原则与未来展望:团队对MRV2设定了更高的质量标准:在将V1功能引入MRV2时,团队会基于第一性原理重新思考,而不是机械地复制复杂性。因此,涉及MRV2的更改可能需要比平时更长的时间才能合并。团队计划在不久的将来使MRV2成为vLLM的默认运行器。
使用方法:用户安装最新的vLLM构建版本后,只需设置环境变量export VLLM_USE_V2_MODEL_RUNNER=1即可启用。该更新不需要任何面向用户的API更改,用户可以像往常一样使用Python API或vllm serve。
补充细节
致谢:本文档的发布和工程实现离不开以下人员的贡献:Woosuk Kwon, Nick Hill, Giancarlo Delfin, Santino Ramos (Inferact), Wentao Ye, Zhanqiu Hu, Lucas Wilkinson (Red Hat), Haoran Zhu (Alibaba)。
💬 评论讨论
欢迎在这里分享您的想法和见解!