vLLM 基本原理

vLLM(Virtual Large Language Model)是一种用于高效、大规模运行大语言模型(LLM)的推理框架。它主要由两部分组成:推理服务器(负责接收和调度请求、管理网络流量)和推理引擎(负责高效执行模型计算)。

vLLM 的核心机制是 PagedAttention 算法,通过更高效地管理和复用 GPU 显存,减少内存碎片和不必要的拷贝,从而显著提升推理效率,加快生成式 AI 应用的响应速度。

vLLM 的总体目标是最大化吞吐量(即每秒可处理的 Token 数),以支持在同一套 GPU 资源上同时为大量用户提供稳定、高性能的推理服务。


vLLM 的核心原理主要有:

  • KV Cache(缓存 Token,即对话的上下文记忆)
  • PagedAttention(核心算法,解决存储碎片)
  • Continuous Batching(连续批处理,解决计算空闲)

KV Cache

Transformer 和 Attention

了解 KV Cache 之前,需要先了解一下 Transformer 和 Attention。

Transformer 是一个反复堆叠的模块,用 Attention 建模上下文关系。

而 Attention 的作用,可以理解为一个加权查询系统:当前 Token 通过 Query,对上下文中所有 Token 的信息进行打分,并加权融合出最相关的表示。

对于每个 Token,模型都会算出:

  • Query:我要找什么?
  • Key:我是什么?
  • Value:我的实际内容是什么?


什么是 KV Cache

LLM 的文本生成是自回归的:每生成一个新 Token,都需要依赖之前所有 Token 的信息。

如果在生成过程中反复重新计算历史 Token 的 Attention,计算复杂度会迅速上升,效率极低。

因此,模型会将历史 Token 在各层 Attention 中计算得到的 Key 和 Value 向量缓存到显存中,这部分缓存称为 KV Cache。

在生成过程中,KV Cache 会随着序列长度增加而不断累积,从而避免重复计算历史 Token。


KV Cache 的痛点

在传统 LLM 推理(如 HuggingFace Transformers)中,KV Cache 通常按请求独占、连续内存的方式管理。

由于无法预知请求的最终生成长度,系统往往需要按最大上下文长度一次性预分配 KV Cache。

这导致大量显存被提前占用却无法充分利用,同时不同长度请求难以混合调度,显存碎片化后系统吞吐迅速下降。


PagedAttention

什么是 PagedAttention

PagedAttention 是 vLLM 的核心算法,它的设计灵感直接来源于操作系统中的虚拟内存(Virtual Memory)和分页(Paging)技术。

PagedAttention 将 KV Cache 的管理分为三个层级:

  1. 逻辑块 (Logical Blocks)
  • 从 Transformer 的视角看,KV Cache 依然是连续的 Token 序列。
  • vLLM 将这个序列切分成固定大小的块(例如 block_size=16)。
  1. 物理块 (Physical Blocks)
  • 从 GPU 显存(VRAM)的视角看,显存被划分为无数个物理块。
  • 这些物理块在显存地址空间中可以是非连续的,散落在任何位置。
  1. 块表 (Block Table)
  • 这是核心组件。类似于 OS 的页表(Page Table)。
  • 它记录了 逻辑块 ID 物理块 ID 的映射关系。
  • 当模型计算 Attention 时,CUDA 内核(Kernel)会根据这张表,去物理显存的各个角落抓取数据进行计算。


PagedAttention 的优点

  1. 按需分配 (On-Demand Allocation)
  • 与传统预分配最大长度不同,PagedAttention 采用动态扩容。
  • 当一个 Block 填满数据后,系统才向显存池申请下一个新的物理 Block。
  • 好处是消除了内部碎片。除了最后一个 Block 可能没填满,其他 Block 都是 100% 利用率。
  1. 非连续存储 (Non-Contiguous Storage)
  • 物理 Block 不需要挨在一起。
  • 好处是消除了外部碎片。只要显存池里剩下的总空间够一个 Block 大小,就能被利用起来,不再需要寻找整块连续的大内存。
  1. 内存共享 (Memory Sharing)
  • 让 AI 基于同一个 Prompt 生成 3 个不同的结局时,3 个输出序列在逻辑上是独立的。
  • 但在物理上,它们的 Prompt 部分(公共前缀)指向同一个物理 Block
  • 只有当它们生成各自不同的新 Token 时,才会分配新的私有 Block。
  • 好处是能够大幅降低复杂任务的显存占用。


Continuous Batching

传统 Batching 的痛点

在 vLLM 出现之前,由于显存必须连续分配,推理引擎使用的是 Static Batching(静态批处理)。

举个例子,当前有四个请求:

  • Req A:短问题,生成的长度只有 10 个词。
  • Req B:长问题,生成的长度有 100 个词。
  • Req C / D:中等长度问题,生成的程度有 50 个词。

在 Static Batching 的工作模式下:

  • 四个请求会同时处理。
  • 由于 Req A 生成长度较短,所以最快完成,但需要等待最长的问题 Req B 也完成后,才能释放资源。
  • 也就是说,在 Req A 等等的这段时间,资源仍然被占用,但却不做任何有效计算,造成资源浪费。


Continuous Batching 工作原理

同样的例子,Continuous Batching 的处理方式为:

  • 四个请求会同时处理。
  • 当 Req A 完成后,会立即释放其占用的资源,给新的请求使用。

Continuous Batching 的工作需要极强的显存管理能力配合。在没有 PagedAttention 之前,Req A 完成后释放的资源,是显存里的一块碎片。如果新来的请求比 Req A 长,根本塞不进去。

只有当显存变成页(Block)式管理后,Req A 释放的 Block 可以立刻分配给新的请求(哪怕该请求的长度需要更多的 Block,也可以先给它几个 Block 跑起来,不够再动态申请),这才实现了真正的 Continuous Batching。


FlashInfer 采样器

FlashInfer 采样器是 vLLM 在 GPU 上执行下一个 Token 选择的一种高性能实现。

LLM 每生成一个 Token,模型都会先输出一组 logits:

1
2
3
4
“你好”      8.2
“您好” 7.9
“今天” 5.1
“苹果” 1.2

这些 logits 表示词表中每个 Token 的相对倾向。采样器负责经过 Temperature、Top-K、Top-P 等处理后,从候选 Token 中选出下一个 Token。vLLM 的标准采样流程包括温度缩放、logit 处理、Top-K/Top-P 过滤以及最终随机采样。


FlashInfer 工作原理

FlashInfer 提供了专门的 CUDA Kernel,用于在 GPU 上完成:

  • Top-K 过滤
  • Top-P 过滤
  • Temperature 处理
  • 概率采样
  • 部分 logits 处理操作

例如请求参数:

1
2
3
4
5
{
"temperature": 0.7,
"top_k": 50,
"top_p": 0.9
}

生成过程大致是:

1
2
3
4
5
6
7
8
9
模型输出 logits

Temperature 调整分布

Top-K 保留概率最高的 K 个 Token

Top-P 保留累计概率达到 P 的 Token

按剩余概率随机选择下一个 Token

FlashInfer 会把其中多个步骤尽量放到融合 CUDA Kernel 中执行,减少中间张量、排序和多次 Kernel 启动带来的开销。

vLLM 官方说明:FlashInfer 与原生随机采样在统计结果上等价,但由于避免对 logits 张量排序,通常执行得更快。

因此,FlashInfer 是为了在相同模型、相同采样参数、相同概率分布的条件下,更高效地选出下一个 Token。


PD 分离

在大语言模型中,一次推理分成了两个阶段:

1
2
3
4
5
用户提示词

Prefill 实例处理全部输入,生成首 Token 和 KV Cache
↓ 传输 KV Cache
Decode 实例根据 KV Cache 逐 Token 生成答案

普通 vLLM 在同一个实例里交替运行 Prefill 和 Decode。长 Prompt 的 Prefill 可能干扰其他请求的 Decode,造成 ITL 抖动。

ITL 是 Inter-Token Latency,即模型连续输出两个 Token 之间的时间间隔。

PD 分离使用两个 vLLM 实例,Prefill 实例负责输入处理、Decode 实例负责生成。

Author

Warner Chen

Posted on

2026-02-02

Updated on

2026-07-27

Licensed under