vllm
吾生也有涯,而知也无涯。——庄子
把显存一寸一寸抠回来:vLLM 的推理引擎长什么样
三个词,一句自我定位
「Easy, fast, and cheap.」
这是 vLLM 给自己写的 slogan,短得有点不像话:简单、快、便宜,人人可用。三个形容词,没有一个是技术名词,但它们恰好对应了部署一个大模型时最疼的三件事——装不起来、跑得太慢、算下来太贵。
它的正式定位也只有一句:一个面向大语言模型的高吞吐、内存高效的推理与服务引擎。
注意这两个限定词。高吞吐说的是一段时间里能吐出多少 token;内存高效说的是这些 token 是用多少显存换来的。这两个词放在一起,其实是一个约束条件的两面:显存是硬的,吞吐是软的,想让吞吐上去,只能在显存的使用方式上做文章。
项目地址:https://github.com/vllm-project/vllm
vLLM 做的所有事情,几乎都可以追溯到这一条线上。
它从哪儿来
这份代码最早诞生在加州大学伯克利分校的 Sky Computing Lab。一个实验室项目,长到今天这个体量——文档里用了一个很克制的说法:它已经成为最活跃的开源 AI 项目之一,由来自几十家学术机构与公司的多元社区共同构建和维护,贡献者超过 2000 人。
2000 多人不是一个可以靠热情维持的数字。它意味着这个项目必须有一套能让陌生人快速接手的工作方式:清晰的贡献路径、公开的讨论场所、可复现的基准、以及足够稳定的接口。这些不写在性能指标里,但它们是「一个项目能不能活过第三年」的分水岭。
快,具体快在哪
文档把「快」拆成了一份相当长的清单。逐条看下来,会发现它们其实在解决四个层次的问题:显存怎么用、请求怎么排、执行怎么走、算力怎么省。
第一层:显存这块,先动刀
清单第一条是「业界领先的服务吞吐」,第二条就给了原因——用 PagedAttention 高效管理注意力的 key 与 value 缓存。
这个设计是整个项目的起点。KV 缓存是推理时最占地方的东西:每个并发请求都要为自己的上下文留一块连续空间,长度还不确定,短的浪费,长的溢出。PagedAttention 的思路是把这块内存像操作系统管内存那样分页管理,让缓存不必连续、不必预留、可以按需拼接。
显存不再被「预留但没用上」的碎片吃掉,能同时容纳的请求数就上去了。吞吐的提升不是算得更快,而是同时算得更多。
第二层:请求不该排队等整批
接着是三个调度层面的机制:连续批处理、分块预填充、前缀缓存。
连续批处理解决的是「批的边界太硬」这个问题。传统做法是攒一批、跑完、再攒一批,一个短请求如果赶上了一个长请求,就得陪它等到最后。连续批处理让新请求可以在任意时刻加入正在跑的批次,一个请求结束,它的位置立刻被下一个填上。
分块预填充把长 prompt 的预填充阶段切成小块,让一个超长输入的请求不至于独霸整个批次。
前缀缓存则针对那些「开头都一样」的请求——系统提示词、few-shot 示例、固定的工具描述。这一段算过一次就可以复用,不必每个请求都重算。
三个机制合起来,效果是同一件事:让 GPU 的空闲周期变少。
第三层:图、核、量化
再往下是执行层。
CUDA/HIP 图,支持分段和整图两种模式。图捕获的意义在于把一长串 kernel 启动的调度开销压成一次提交,尤其在解码这种每步计算量小、启动次数多的场景里,省下来的时间比例很可观。
量化这张清单长得有点夸张:FP8、MXFP8、MXFP4、NVFP4、INT8、INT4、GPTQ、AWQ、GGUF、compressed-tensors、ModelOpt、TorchAO,后面还跟着「以及更多」。这不是为了显得全,而是因为现实里的模型权重就是各种格式混杂的,一个服务引擎如果只认一种,用户就得先做一轮转换。
注意力 kernel 支持 FlashAttention、FlashInfer、TRTLLM-GEN、FlashMLA 和 Triton。GEMM 与 MoE kernel 覆盖多种精度,用 CUTLASS、TRTLLM-GEN、CuTeDSL 实现。
这些名字背后是同一个现实:注意力机制和专家混合这两块最吃算力,也最依赖硬件细节。不同显卡、不同精度、不同序列长度,最优实现都不一样,所以这里给的不是一个 kernel,而是一排。
torch.compile 在这里承担了自动化的角色——自动生成 kernel,做图级变换。手写 kernel 能榨出最后几个百分点,但它需要人;编译器能覆盖那些没人愿意为它手写 kernel 的形状。两条腿走路。
第四层:先猜,再验
投机解码是另一条思路:用小模型或者规则先猜出若干个 token,再用大模型一次性验证。猜对了就白赚,猜错了就回退。
vLLM 支持四种:n-gram、suffix、EAGLE、DFlash。四种方法对应四种「猜」的来源——从输入文本本身找重复片段,从上下文里找后缀匹配,用专门训练的小模型来猜,或者用更轻的扩散式方案。
这条路的天花板取决于「猜得准不准」,而准不准又取决于任务本身。代码补全、结构化输出、长文档改写,这些场景里重复和规律多,投机解码的收益就明显;自由创作里就未必。
还有一条:把流水线拆开
分离式 prefill、decode 和 encode,是把推理的不同阶段放到不同机器上跑。
预填充是算力密集的,一次要吞下整个 prompt;解码是显存带宽密集的,每步只吐一个 token。把这两件事塞在同一张卡上,等于让一台机器同时干两种性格完全相反的工作。拆开之后,各自的资源可以按各自的节奏扩缩。
好用,具体好用在哪
性能清单看完,再看易用性清单,会发现语气变了:不再是「我们支持多少种格式」,而是「你原来怎么用,现在还能怎么用」。
与 Hugging Face 上的主流模型无缝集成。 这一条是整份文档里最重要的一句工程承诺。它意味着你不需要为了换引擎而重写模型定义、重新导出权重、重新对齐分词器。
多种解码算法的高吞吐服务,包括并行采样、束搜索,以及更多。批量生成多个候选、做 reranking、做 self-consistency,这些都不必自己在外层拼装。
五种并行:张量并行、流水线并行、数据并行、专家并行、上下文并行。前三种是常规手段,专家并行针对 MoE 结构,上下文并行则服务于那些长到一张卡放不下的序列。
流式输出。 一个字一个字往外吐,而不是等整段生成完。
结构化输出,通过 xgrammar 或 guidance 实现。这两套都是把语法约束塞进解码过程,让模型从一开始就只能生成合法的 JSON、正则匹配的字符串或者某种 DSL。
工具调用与推理解析器。 前者让模型输出可以被直接解析成函数调用,后者负责把思维链和最终答案分开——这两件事现在更像服务层该有的能力,而不只是应用层的小技巧。
OpenAI 兼容的 API 服务,另外还支持 Anthropic Messages API 和 gRPC。三种入口对应三类用户:已经写好 OpenAI SDK 调用的、用 Claude 那套消息格式的、以及需要强类型接口和高性能传输的。
面向稠密层与 MoE 层的高效 multi-LoRA。 一个基座模型挂多个适配器,各租户各用各的,权重共享。这条对做 SaaS 的团队尤其重要——它把「一个客户一个模型」的成本压回了「一个模型多个适配器」。
硬件版图:不止 NVIDIA
支持的硬件分两类写:原生支持的和靠插件接进来的。
原生支持 NVIDIA GPU、AMD GPU、Intel GPU,以及 x86、ARM、PowerPC 架构的 CPU。
插件生态则拉得更开:Google TPU、Intel Gaudi、IBM Spyre、华为昇腾、Rebellions NPU、Apple Silicon、MetaX GPU,以及更多。
把这份名单读一遍,能看出一个很现实的考量。推理引擎的护城河不在模型,在硬件适配——每多支持一种卡,就多一群能用它的人。而插件机制的意义在于,这件事不必由核心团队一个人一个人地做。
200+ 模型架构,六类
文档说它无缝支持 Hugging Face 上 200 多种模型架构,然后按六类举例:
纯解码器 LLM,比如 Llama、Qwen、Gemma。这是最主流的一类。
专家混合 LLM,比如 Mixtral、DeepSeek-V3、Qwen-MoE、GPT-OSS。这类模型的参数总量很大但每步只激活一部分,对调度和显存管理的要求比稠密模型更高。
混合注意力与状态空间模型,比如 Mamba、Qwen3.5。这一类的计算模式和 Transformer 不一样,能支持它说明引擎的抽象层留了足够的余地。
多模态模型,比如 LLaVA、Qwen-VL、Pixtral。图像要被编码成 token 才能进语言模型,这条链路要单独打通。
嵌入与检索模型,比如 E5-Mistral、GTE、ColBERT。这一类不生成文本,只吐向量,服务形态完全不同。
奖励与分类模型,比如 Qwen-Math。输出是一个分数或者一个标签,而不是一段话。
六类放在一起看,vLLM 想覆盖的其实不是「文本生成」,而是「模型前向计算的任何一种用法」。
装起来只要两行
文档推荐的安装方式是用 uv,也支持 pip:
1 | uv pip install vllm |
第一行装包,第二行把预编译好的 kernel 拉下来,换一个更快的启动速度。
如果是要做开发,也可以从源码构建。这条路径通向的是另一件事:改代码、提 PR、参与这个 2000 多人的协作。
名字背后那篇论文
vLLM 不是一个凭空冒出来的工程实践,它有一篇对应的论文,题目是《Efficient Memory Management for Large Language Model Serving with PagedAttention》,发表在 ACM SIGOPS 第 29 届操作系统原理研讨会上。
题目已经把核心讲完了:用 PagedAttention 做高效的大模型服务内存管理。前面讲的 KV 缓存分页、连续批处理、吞吐提升,都是这篇论文的工程化延伸。
这也是这个项目比较特别的地方——它的性能优势来自一个可以被复述、被检验、被引用的机制,而不是一堆调参技巧的堆叠。机制可以被别人重新实现,技巧不行。
一个项目怎么长大
文档里关于「如何参与」的部分写得很平,但值得念一遍:技术问题和功能请求走 GitHub Issues;和同行讨论去 vLLM 论坛;协调贡献和开发去 Slack;安全漏洞走 GitHub 的安全公告渠道;合作与伙伴关系另有专门的联络方式。
这五条对应的其实是五种不同的关系:使用者、同行、贡献者、安全研究者、商业伙伴。一个项目能同时容下这五种人,才有了从实验室项目变成基础设施的可能。
至于 logo 的使用,文档单独指了一个 media kit 仓库——这种事写得越清楚,越说明它已经被人惦记过很多次了。
最后
回到那三个词。
Easy 是把复杂度收进引擎内部,让调用方看到的仍然是一个 OpenAI 兼容的接口。Fast 是把显存、调度、kernel、解码四层一起优化,而不是只在一个点上做文章。Cheap 是前两者的结果——同样的卡,跑出更多的 token,单位成本自然就下来了。
PagedAttention 这个设计的迷人之处,在于它借了一个非常古老的思路:内存不该被一整块一整块地占着,应该被切成页,按需分配。操作系统几十年前就学会了这件事,vLLM 只是把它搬到了注意力的 KV 缓存上。
有时候让一个领域往前跳一步的,不是什么新发明,而是一个从别处借来的旧常识。
