大模型推理基础:Transformer架构、自回归生成与KV Cache原理

要理解 vLLM 与 TensorRT-LLM 在吞吐调优上的差异,首先必须回到大模型推理的底层运行机制。吞吐量的瓶颈并非单纯来自 GPU 的浮点算力,而是由 Transformer 的解码方式、自回归生成顺序以及 KV Cache 的内存增长模式共同决定。本节将拆解这三个核心概念,并揭示它们如何直接制约推理引擎的调度策略。

2.1 Transformer 架构:从 Encoder 到 Decoder 的推理差异

现代大语言模型(如 GPT、LLaMA、Qwen)几乎都采用 Decoder-only 架构。与早期 Transformer 的 Encoder-Decoder 结构不同,Decoder-only 模型在推理时没有独立的编码阶段,而是直接对输入序列进行自回归处理。其核心组件包括:

  • 多头自注意力(Multi-Head Attention):每个 Token 都要与序列中所有之前的 Token 计算相关性,生成 Query、Key、Value 向量。
  • 前馈网络(FFN):对注意力输出进行非线性变换,通常占据模型约 2/3 的参数。
  • 层归一化与残差连接:稳定深层网络训练与推理的数值流。

在推理阶段,Decoder-only 模型存在两种典型模式:

模式 触发场景 计算特征
Prefill(预填充) 用户输入提示词(Prompt) 并行处理所有输入 Token,计算密集,GPU 利用率高
Decode(解码) 逐个生成输出 Token 串行处理单个 Token,访存密集,GPU 利用率低

吞吐调优的核心矛盾在于:Prefill 阶段需要高算力,Decode 阶段需要高带宽。vLLM 与 TensorRT-LLM 的调度器本质上都在解决这两种阶段混合时的资源分配问题。

关键认知:吞吐量(Tokens/s)并非由单次推理速度决定,而是由“单位时间内完成多少个请求的生成”决定。因此,批处理(Batching)策略比单请求延迟更重要。

2.2 自回归生成:串行依赖与条件概率

自回归(Autoregressive)生成是指模型将 已生成的 Token 序列作为下一步预测的输入。数学上表示为:

P(y₁, y₂, ..., yₙ | x) = Π P(yₜ | x, y₁, ..., yₜ₋₁)

这意味着第 t 个 Token 的生成必须等待前 t-1 个 Token 全部完成。这种串行依赖导致两个重要推论:

  1. 无法并行生成同一序列内的 Token——即使 GPU 有数千个核心,单请求的 Decode 步骤也只能一次推进一个 Token。
  2. 序列长度动态增长——每个请求的最终长度未知,导致显存分配无法预先精确规划。

为了提升吞吐,推理引擎采用 连续批处理(Continuous Batching):不再等待整个批次全部完成,而是当批次中某个请求生成完毕(如遇到 EOS 或达到 max_tokens)时,立即插入新请求。这要求引擎能够动态管理每个请求的中间状态。

吞吐调优启示:自回归的串行性决定了“批大小”是吞吐量的第一杠杆。但增大批大小会线性增加 KV Cache 显存占用,因此引擎必须在批大小与显存容量之间做动态权衡。

2.3 KV Cache:推理吞吐的显存瓶颈

KV Cache 是 Transformer 推理中最关键也最容易被忽视的机制。在 Decode 阶段,每个新 Token 的注意力计算需要与历史所有 Token 的 Key 和 Value 向量做点积。若不缓存,则每次都要重新计算历史 Token 的 K/V,计算量随序列长度平方增长,完全不可接受。

KV Cache 的显存占用公式为:

KV Cache 显存 = 2 (K 和 V) × 层数 × 注意力头数 × 头维度 × 序列长度 × 批大小 × 每个元素字节数

以 LLaMA-7B 为例(32 层,32 头,头维度 128,FP16):

每 Token 每请求的 KV Cache = 2 × 32 × 32 × 128 × 2 字节 = 512 KB

当批大小为 64、平均序列长度为 1024 时,仅 KV Cache 就占用:

512 KB × 1024 × 64 = 32 GB

这已经超过许多单张 GPU 的显存容量。因此,KV Cache 的管理方式直接决定了推理引擎能否支持更大的并发批处理。

常见误区:许多人认为显存主要被模型权重占用。实际上,在长序列、大并发场景下,KV Cache 的显存占用往往超过模型权重本身。这也是 vLLM 引入 PagedAttention 的核心理由。

2.4 可视化:Transformer 推理数据流与 KV Cache 增长

下图展示了 Decoder-only 模型在 Prefill 与 Decode 阶段的数据流差异,以及 KV Cache 如何随生成过程动态增长。左侧为 Prefill 阶段并行处理输入 Token,右侧为 Decode 阶段逐个生成并持续追加 KV Cache。

Prefill 阶段(并行处理) Token₁ Token₂ Token₃ Token₄ 多头自注意力 并行计算所有 Token 的注意力 前馈网络 (FFN) 逐 Token 独立变换 生成首个输出 Token KV Cache 初始填充 为每个输入 Token 计算并存储 K/V 序列长度 = 4 Decode 阶段(串行生成) Token₁ Token₂ Token₃ Token₄ Token₅ 当前生成 多头自注意力 新 Token 与所有历史 Token 计算 读取 前馈网络 (FFN) 预测下一个 Token 概率分布 KV Cache 动态追加 新 Token 的 K/V 追加到缓存 序列长度 = 5 → 6 → 7 ... 循环直到 EOS Prefill:计算密集,可并行 Decode:访存密集,串行 + KV Cache 持续增长

图中清晰展示了两个阶段的本质区别:Prefill 阶段一次性处理所有输入 Token,计算完成后生成 KV Cache 的初始版本;Decode 阶段则每次只处理一个 Token,但需要从 KV Cache 中读取历史信息,并将新 Token 的 K/V 追加到缓存中。随着生成推进,KV Cache 的显存占用呈线性增长,这直接限制了批处理大小。

2.5 吞吐调优的核心矛盾与误区复盘

基于上述原理,可以总结吞吐调优的三大核心矛盾:

  • 算力 vs. 带宽:Prefill 需要算力,Decode 需要带宽。混合批处理时,引擎必须决定 GPU 资源在两种计算模式间的分配比例。
  • 批大小 vs. KV Cache 容量:增大批大小能提升吞吐,但 KV Cache 占用随之线性增长,显存不足时只能降低批大小或使用更小的模型。
  • 动态长度 vs. 静态分配:请求的最终长度未知,若按最大长度预分配显存,将造成巨大浪费;若动态分配,则面临碎片化问题。
典型误区复盘:初学者常认为“只要 GPU 算力够大,吞吐就高”。实际上,在 Decode 阶段,GPU 计算单元大量空闲,瓶颈在于从显存中读取 KV Cache 的带宽。这也是为什么 vLLM 的 PagedAttention 和 TensorRT-LLM 的 KV Cache 优化都聚焦于显存管理而非算力提升。