← 返回目录 模块 1 / 8

1.1 Prefill / Decode 阶段

核心概念

LLM 推理过程本质上分为两个截然不同的计算阶段:Prefill(预填充/上下文处理)和 Decode(解码/自回归生成)。Prefill 阶段接收完整的输入 prompt token 序列,通过一次前向传播计算所有 prompt token 的 KV Cache,同时生成第一个输出 token。Decode 阶段则进入自回归循环,每次只处理一个新 token,利用已缓存的 KV Cache 逐 token 生成后续输出 [S1][S2]。

Prefill 阶段的计算特性

Prefill 阶段具有以下核心特征:

  1. 计算密集型(Compute-bound):Prefill 一次性处理整个 prompt(如 4096 tokens),可以充分利用 GPU 的矩阵乘法并行性。Attention 计算复杂度为 O(n²)(n = prompt 长度),当 n 较大时,计算量非常可观。
  2. 内存写入为主:Prefill 阶段需要将每层的 Key 和 Value 张量写入 KV Cache。对于 L 层、H 个 KV head、head dimension D 的模型,每个 token 的 KV Cache 大小为:
  3. Batch 效应显著:Prefill 阶段将多个请求的 prompt 拼接后一起处理,可以摊薄 kernel launch 开销和权重加载开销。
per_token_kv_size = 2 * L * H * D * dtype_size

其中 2 表示 Key 和 Value 两组张量,dtype_size 为数据类型字节数(FP16 为 2 字节,FP8 为 1 字节)。

Decode 阶段的计算特性

Decode 阶段具有以下核心特征:

  1. 内存带宽密集型(Memory-bound):Decode 每次只处理 1 个新 token(或少量 speculative tokens),计算量很小。主要开销在于从 HBM(高带宽显存)读取庞大的模型参数和 KV Cache。对于 70B 模型(FP16,约 140GB 参数),在 A100(HBM 带宽 2TB/s)上,理论最小 TPOT(Time Per Output Token)约为 70ms/token(无 batching 时)。
  2. KV Cache 读取主导:Decode 阶段需要读取之前所有 token 的 KV Cache。对于长序列(如 128K tokens),KV Cache 读取量可能超过模型参数读取量,成为主要瓶颈。
  3. Sequential 性质:Decode 必须严格按顺序生成 token,无法像 Prefill 那样利用序列内并行性。

关键指标公式

指标公式说明
TTFTt_first_token_output - t_request_received从请求到第一个输出 token 的时间,主要由 Prefill 决定
TPOTTotal decode time / (Output tokens - 1)每个输出 token 的平均时间,反映 Decode 速度
ITLt_{i+1} - t_i相邻 token 间隔,反映生成平滑度
E2E LatencyTTFT + (Output length - 1) * TPOT端到端总延迟
Prefill FLOPsapprox 2 * B * n² * dBatch size B,序列长度 n,模型维度 d
Decode FLOPs/tokenapprox 2 * B * n * d每生成一个 token 的计算量

Prefill 与 Decode 的关系

Prefill 是 Decode 的前置条件:没有 Prefill 阶段计算的 KV Cache,Decode 阶段无法开始。在传统系统中,当一个长 prompt 请求进入时,它会在一个 step 中独占整个 GPU 执行 Prefill,期间所有正在 Decode 的请求必须等待,导致它们的 ITL 急剧增加。这是 Chunked Prefill(模块二)和 Disaggregated Serving(模块四)等技术要解决的核心问题。

资源需求矛盾:Prefill 需要强算力、大 batch(摊薄开销);Decode 需要高内存带宽、低延迟、持续调度。当两者混合在同一 GPU 上时,Prefill 会抢占 Decode 的计算资源,导致 Decode token 延迟剧增。

1.2 KV Cache

存储优化

KV Cache(Key-Value Cache)是 LLM 推理中的核心优化技术。在 Transformer 的自回归生成过程中,每个新 token 的 Attention 计算需要与之前所有 token 的 Key 和 Value 进行交互。如果每次都重新计算所有历史 token 的 K 和 V,将产生大量的重复计算。KV Cache 技术将之前计算过的 Key 和 Value 张量缓存起来,在后续步骤中直接复用,从而将每步的计算复杂度从 O(n²) 降低到 O(n)(n 为序列长度)[S1]。

KV Cache 大小计算公式

对于单个请求,KV Cache 的总大小为:

KV_Cache_Size = 2 * L * S * H * D * dtype_size

其中:

  • L = 模型层数(如 LLaMA-70B 有 80 层)
  • S = 当前序列长度(已生成的 token 数)
  • H = KV head 数量(如 LLaMA-70B 有 8 个 KV head)
  • D = head dimension(如 128)
  • 2 = Key 和 Value 两组张量
  • dtype_size = 数据类型字节数

示例:LLaMA3-70B(FP16)每 token 的 KV Cache:

2 * 80 * 1 * 8 * 128 * 2 = 327,680 bytes approx 320 KB

对于 4K context,KV Cache approx 1.28 GB;对于 128K context,KV Cache approx 40 GB。

传统分配的问题

在 PagedAttention 出现之前,主流推理系统为每个请求预分配一块连续的 GPU 内存,容量按该请求的最大可能序列长度计算。这种方案的内存浪费来源包括 [S1][S29]:

  1. 内部碎片(Internal Fragmentation):大多数请求的实际生成长度远小于最大长度。若 max_model_len = 4096 但平均输出长度仅 256,则内部碎片率约为 (4096 - 256) / 4096 ≈ 93.75%。
  2. 外部碎片(External Fragmentation):不同请求释放内存后,剩余空闲块可能不连续,导致后续大请求无法分配,即使总空闲内存足够。
  3. 冗余复制(Redundant Duplication):在并行采样(parallel sampling)和束搜索(beam search)中,多个序列共享相同的前缀 prompt,但传统方案为每个序列独立存储完整的 KV Cache,导致前缀部分被重复存储多次。

vLLM 论文报告的实验数据显示,在 OPT-13B 模型和 Alpaca trace 上,传统方案的 KV Cache 内存利用率通常只有 20-40%,而 PagedAttention 可将利用率提升至 95% 以上。

KV Cache 与 PagedAttention 的关系

KV Cache 是 PagedAttention 的管理对象。PagedAttention 本质上是一种 KV Cache 的内存管理方案,它将 KV Cache 分为固定大小的 block,通过 Block Table 实现逻辑到物理的非连续映射。没有 KV Cache 的概念,PagedAttention 就失去了管理目标;没有 PagedAttention,KV Cache 的内存利用效率极低。

1.3 Attention Mechanism

核心概念

Attention Mechanism(注意力机制)是 Transformer 架构的核心组件,它允许模型在处理序列时动态地关注输入的不同部分。Self-Attention(自注意力)是 Attention 的一种特殊形式,其中 Query、Key、Value 都来源于同一个输入序列,使模型能够捕捉序列内部任意两个位置之间的依赖关系 [S1]。

Self-Attention 完整数学公式

对于输入序列 X ∈ R^{n × d_model},Self-Attention 的计算步骤如下:

Step 1: Q/K/V 投影

Q = X WQ, K = X WK, V = X WV

其中 WQ, WK, WV ∈ R^{d_model × d_k} 是可学习的投影矩阵。

Step 2: 缩放点积

scorei,j = (qi · kj) / √(dk)

除以 √(d_k) 的缩放因子是为了防止当 d_k 较大时点积数值过大,导致 softmax 进入梯度饱和区。

Step 3: Softmax 归一化

αi,j = softmax( (qi · kj) / √(dk) )j = exp( (qi · kj) / √(dk) ) / Σl=1n exp( (qi · kl) / √(dk) )

在 Decoder 的自注意力中,还需要应用因果掩码(Causal Mask)M:

αi,j = softmax( (qi · kj) / √(dk) + Mi,j )

其中 Mi,j = 0 如果 j ≤ i,否则 Mi,j = -∞。

Step 4: 加权聚合

Attention(Q, K, V) = softmax( Q KT / √(dk) ) V

Multi-Head Attention(MHA)

Multi-Head Attention 通过并行运行多组独立的注意力机制,让模型同时从多个表示子空间中捕捉不同类型的关系:

headi = Attention(Q WiQ, K WiK, V WiV)
MultiHead(Q, K, V) = Concat(head1, head2, ..., headh) WO

其中 WO ∈ R^{h d_v × d_model} 是最终的输出投影矩阵。

MHA / MQA / GQA 对比

特性MHA(Multi-Head Attention)MQA(Multi-Query Attention)GQA(Grouped-Query Attention)
定义每个头有独立的 Q/K/V 投影所有头共享同一组 K/VK/V head 数介于 MHA 和 MQA 之间
KV Cache 大小O(n · h · d)O(n · 1 · d)O(n · g · d)
内存效率低高中等
质量损失无(基线)可能有轻微损失损失较小
代表模型原始 TransformerPaLMLLaMA-2/3, Mistral
适用场景追求质量优先极致内存压缩质量与效率平衡

GQA 的具体机制:将 h 个 Query head 分成 g 组(g < h),每组共享一组 K/V。例如 LLaMA-2 有 32 个 Q head 和 8 个 KV head(g = 8),即每 4 个 Q head 共享 1 个 KV head。这减少了 KV Cache 到 1/4,同时质量损失远小于 MQA。

Attention 与 KV Cache 的关系

Attention 的计算依赖 KV Cache:在 Decode 阶段,Attention 的计算公式变为:

Attention(qt, K≤t, V≤t) = softmax( qt K≤tT / √(dk) ) V≤t

其中 K≤t 和 V≤t 就是 KV Cache 中存储的历史 Key 和 Value。没有 KV Cache,每次 Decode 都需要重新计算所有历史 token 的 K 和 V,计算量从 O(n) 暴涨到 O(n²)。

Attention 与 PagedAttention 的关系

PagedAttention 要求 Attention Kernel 支持非连续 KV Cache 访问。传统 Attention Kernel 假设 K 和 V 是连续的内存块,而 PagedAttention 的 K 和 V 存储在分散的物理 block 中。因此,FlashAttention、FlashInfer 等后端需要接收 block table(物理块 ID 列表)和 slot mapping(每个 token 对应的物理块内偏移),而非连续的内存指针 [S12]。

← 返回目录
封面与导航
下一模块 →
vLLM 核心创新