LLM推理基础:Transformer架构、自回归生成与KV Cache概念

要理解vLLM为何能实现高吞吐、低延迟的推理,首先必须回到大语言模型(LLM)推理的底层机制。绝大多数现代LLM(如GPT、Llama、Qwen)都基于Transformer解码器架构,其推理过程由两个核心机制主导:自回归生成与KV Cache。本节将拆解这三块基石,并揭示它们如何共同决定了推理系统的性能瓶颈。

2.1 Transformer解码器:推理的基本单元

LLM的推理并非一次性生成整段文本,而是逐token(词元)进行的。每个token的生成都经过一次完整的前向传播,其核心计算发生在Transformer解码器层中。一个典型的解码器层包含以下关键子模块:

  • 自注意力(Self-Attention):让每个位置都能“看到”序列中所有其他位置,计算它们之间的关联权重。这是模型理解上下文的核心机制。
  • 前馈网络(FFN):对每个位置的表示进行独立的非线性变换,通常包含两个线性层和一个激活函数(如SiLU或GELU)。
  • 层归一化(LayerNorm)与残差连接:稳定训练和推理过程中的数值流动,加速收敛。

在推理时,输入序列(即当前已生成的所有token)会依次通过所有解码器层。每一层都输出一个同样长度的向量序列,最终经过一个输出投影层(lm_head),将最后一个位置的隐藏状态映射为词表大小的概率分布,从中采样或贪心地选出下一个token。

核心计算视角:推理时的计算量主要由两部分构成:注意力计算(QK^T 矩阵乘法)和 FFN计算(两个大矩阵乘法)。其中,注意力计算的时间复杂度与序列长度的平方成正比(O(n²)),而FFN计算与序列长度成正比(O(n))。当序列变长时,注意力计算将成为主要瓶颈。

Transformer解码器层推理数据流(单token生成) 输入Token序列 [t1, t2, ..., tn] ① 自注意力 (Self-Attention) Q = X·Wq, K = X·Wk, V = X·Wv Attention = softmax(QKᵀ/√d)·V 残差连接 LayerNorm ② 前馈网络 (FFN) FFN(x) = GELU(x·W₁ + b₁)·W₂ + b₂ 中间维度通常为 4×hidden_size 输出隐藏状态 → 下一个token概率 ⚡ 计算瓶颈 QKᵀ 矩阵乘法:O(n²·d) n=序列长度, d=隐藏维度 ⚡ 计算密集 两个大矩阵乘法:O(n·d²) 权重矩阵占用显存大头

2.2 自回归生成:逐token的循环过程

LLM的文本生成是一个典型的自回归(Autoregressive)过程:模型将已生成的token序列作为输入,预测下一个token,然后将新token拼接回输入序列,继续预测下一个,如此循环往复,直到遇到终止符(如 <eos>)或达到最大长度。

以生成“人工智能”为例,其过程如下:

  1. 初始化:输入起始符 <s>,模型预测第一个token“人”。
  2. 第1步:输入 <s>人,模型预测“工”。
  3. 第2步:输入 <s>人工,模型预测“智”。
  4. 第3步:输入 <s>人工智能,模型预测“<eos>”,生成结束。

这个循环中,每一步都依赖前一步的输出,因此无法并行生成。这是LLM推理延迟的根本来源。然而,仔细观察会发现一个关键现象:在第2步时,输入序列为 <s>人工,其中前两个token <s>人 与第1步完全相同,但模型却要重新计算它们的注意力表示——这显然是巨大的浪费。

关键洞察:自回归生成中,每一步的输入只比上一步多一个token。对于已计算过的历史token,其K(Key)和V(Value)向量在每一步都是完全相同的(因为它们的上下文没有变化)。因此,我们可以将这些向量缓存起来,避免重复计算。

2.3 KV Cache:消除重复计算的利器

KV Cache(键值缓存)正是为了解决上述重复计算问题而设计的。在推理过程中,每生成一个token,我们将其对应的K向量和V向量保存到显存中。在后续步骤中,只需计算新token的Q、K、V,然后用新token的Q与所有历史K做注意力计算,用所有历史V加权求和即可。

下图对比了有无KV Cache时的计算差异:

步骤 无KV Cache(重复计算) 有KV Cache(增量计算)
第1步 计算 token1 的 K,V 计算 token1 的 K,V,存入缓存
第2步 重新计算 token1 的 K,V + 计算 token2 的 K,V 仅计算 token2 的 K,V,从缓存读取 token1 的 K,V
第3步 重新计算 token1,2 的 K,V + 计算 token3 的 K,V 仅计算 token3 的 K,V,从缓存读取 token1,2 的 K,V
总计算量 O(n²) 次K/V计算 O(n) 次K/V计算

KV Cache带来的性能提升是显著的:对于生成长度为n的序列,它将注意力计算的时间复杂度从O(n²)降为O(n)(仅计算新token的注意力),同时避免了历史token的重复前向传播。在vLLM中,KV Cache的管理是核心优化点之一——它占用了推理时的大部分显存,且其分配策略直接影响系统的吞吐量。

重要权衡:KV Cache以显存换计算。对于7B模型,每个token的KV Cache大小约为 2 × num_layers × num_heads × head_dim × 2 bytes(以FP16计)。例如,Llama-2-7B(32层,32头,head_dim=128)每个token的KV Cache约为 2 × 32 × 32 × 128 × 2 = 512KB。生成1024个token时,仅KV Cache就需要约512MB显存。因此,KV Cache的显存管理是推理系统设计的核心挑战。

2.4 案例:一次完整的推理过程

假设我们使用一个简化模型(2层Transformer,hidden_size=4)生成“深度学习”这四个字。其推理过程如下:

输入: <s>
第1步: 计算 <s> 的 K,V → 缓存
       预测下一个token: "深" (概率最高)
输入: <s> 深
第2步: 仅计算 "深" 的 K,V → 追加到缓存
       用 "深" 的Q与缓存中所有K计算注意力
       预测下一个token: "度"
输入: <s> 深度
第3步: 仅计算 "度" 的 K,V → 追加到缓存
       预测下一个token: "学"
输入: <s> 深度学习
第4步: 仅计算 "学" 的 K,V → 追加到缓存
       预测下一个token: "<eos>"
生成结束: "深度学习"

每一步中,模型只对最新token执行完整的QKV计算和FFN计算,而历史token的K/V直接从缓存中读取。这大大减少了每一步的计算量,使得生成速度主要受限于显存带宽(读取KV Cache)而非计算能力。

2.5 常见误区与复盘

  • 误区1:认为KV Cache是模型参数的一部分。实际上,KV Cache是推理过程中动态生成的临时数据,不参与模型训练,也不属于权重。它只存在于推理时的显存中。
  • 误区2:忽略KV Cache的显存占用。许多初学者只关注模型权重的大小(如7B模型约14GB FP16),却忽略了KV Cache可能占据与权重相当甚至更多的显存。在长序列生成或高并发场景下,KV Cache往往是显存压力的主要来源。
  • 误区3:认为自回归生成可以完全并行。由于每一步依赖前一步的输出,自回归本质上是串行的。但可以通过投机采样(Speculative Decoding)等技术,用小模型草拟多个候选token,再用大模型并行验证,从而在保持质量的同时加速。
  • 误区4:混淆训练和推理的注意力计算。训练时,所有token的Q/K/V可以一次性并行计算(因为输入是完整的);推理时,由于自回归特性,必须逐步计算。KV Cache正是利用了推理时“历史token的K/V不变”这一特性。

本节要点回顾:

  • Transformer解码器由自注意力和FFN组成,推理时逐token前向传播。
  • 自回归生成是串行过程,每一步依赖前一步输出,无法并行。
  • KV Cache缓存历史token的K/V向量,将注意力计算从O(n²)降为O(n)。
  • KV Cache以显存换计算,其显存管理是推理系统(如vLLM)的核心优化方向。