2、LLM推理基础:Transformer架构、自回归生成、KV Cache、预填充与解码阶段、吞吐量与延迟等核心概念

要深入理解主流LLM推理引擎(如vLLM、TensorRT-LLM、SGLang等)的设计哲学与优化手段,首先必须牢固掌握LLM推理的底层机制。推理引擎的每一项优化——从PagedAttention到Continuous Batching,从算子融合到量化——本质上都是在解决Transformer自回归解码过程中的特定瓶颈。本章将系统拆解LLM推理的五大核心概念:Transformer架构的推理视角、自回归生成范式、KV Cache机制、预填充与解码两阶段模型,以及吞吐量与延迟的性能指标体系。这些概念是后续章节对比各推理引擎功能特性的“通用语言”,也是进行性能调优和容量规划的理论基础。

LLM推理核心概念关系图 Transformer解码器 自注意力 + FFN 层归一化 + 残差 Q/K/V 线性投影 位置编码 (推理时权重固定) KV Cache 形状: [2, B, H, S, D] K Cache / V Cache 随序列长度线性增长 显存占用主要瓶颈 (推理引擎优化核心) 自回归生成 输入: "中国的首都是" Step1: 预测 "北" → 拼接 Step2: 预测 "京" → 拼接 Step3: 预测 "。" → 停止 (逐生成,无法并行) 预填充阶段 (Prefill) 处理整个输入提示词 计算密集型,可并行 生成首个 + 填充KV Cache 解码阶段 (Decode) 逐生成后续内容 访存密集型,难并行 读取KV Cache + 计算当前 性能指标 吞吐量 (Tokens/s) = 总生成数 / 总耗时 延迟 (TTFT / TPOT) = 首时间 / 每时间

上图勾勒了LLM推理的核心要素及其相互关系。Transformer解码器是计算主体,自回归生成定义了逐的交互模式,KV Cache是连接预填充与解码阶段的“记忆”载体,而吞吐量与延迟则是衡量整个系统效率的最终标尺。下面我们逐一深入剖析。

2.1 Transformer架构的推理视角

核心原理:从训练到推理的范式转换

现代LLM(如系列、Llama系列、Qwen系列)均基于Transformer解码器架构。在推理阶段,模型权重已固定(除非涉及微调),网络的前向传播过程不再有反向传播和梯度更新。这意味着推理时的计算图是静态的,这为推理引擎提供了极大的优化空间——例如算子融合(将多个线性变换合并)、层间融合、以及针对特定GPU架构的kernel定制。

从推理视角看,Transformer解码器层主要由两个子层构成:掩码多头自注意力(Masked Multi-Head Attention)和前馈神经网络(FFN)。自注意力机制允许模型在生成当前时,关注输入序列中所有之前的位置(包括当前),从而捕捉长距离依赖。FFN则对每个位置的表示进行非线性变换,增强模型的表达能力。此外,层归一化(LayerNorm)和残差连接(Residual Connection)贯穿其中,保证训练稳定性和深层网络的梯度流动。

组件训练阶段行为推理阶段行为推理引擎优化关注点
Q/K/V线性投影计算所有的Q/K/V仅计算当前的Q,K/V从Cache读取矩阵乘法算子融合、精度校准
注意力分数计算并行计算所有位置仅计算当前与历史位置的分数访存优化、FlashAttention
FFN层并行处理所有仅处理当前的表示算子融合、量化(INT8/FP8)
LayerNorm基于batch统计基于单统计kernel融合、减少内存往返

判断方法:如何识别推理架构的瓶颈

在推理引擎的Profiling工具(如Nsight Compute、PyTorch Profiler)中,我们常看到两类瓶颈:计算瓶颈(Compute-bound)和访存瓶颈(Memory-bound)。对于Transformer推理,预填充阶段通常表现为计算瓶颈(大量矩阵乘法),而解码阶段则几乎总是访存瓶颈(因为每次只生成一个,但需要读取整个KV Cache和模型权重)。判断方法是观察GPU利用率(SM Occupancy)和内存带宽利用率。如果SM占用率高但内存带宽利用率低,则是计算瓶颈;反之则是访存瓶颈。

经验提醒:在解码阶段,模型权重本身(如7B模型约14GB FP16)也需要从HBM读取到SRAM,这比读取KV Cache的带宽消耗更大。因此,权重量化(如INT8/FP8)是提升解码速度最直接的手段之一,因为它直接减少了需要搬运的数据量。

案例拆解:Llama-2-7B的推理计算量估算

假设输入序列长度为128,输出序列长度为128。对于Llama-2-7B(32层,隐藏维度4096),预填充阶段需要处理128个的矩阵乘法,计算量约为 2 * 128 * 4096 * 4096 * 32 ≈ 137 GFLOPs。而解码阶段每生成一个,计算量仅为 2 * 1 * 4096 * 4096 * 32 ≈ 1.07 GFLOPs。然而,解码阶段需要读取的KV Cache大小为 2 * 32 * 128 * 4096 * 2 bytes ≈ 67 MB(FP16),加上模型权重14GB,总访存量远大于计算量。这清晰地解释了为何解码阶段是访存瓶颈。

常见误区:忽略“权重访存”

许多初学者认为KV Cache是解码阶段唯一的访存开销。实际上,模型权重的访存开销远大于KV Cache。以7B模型为例,每生成一个,必须读取全部14GB权重(FP16),而KV Cache在长上下文时可能只有几百MB。因此,推理引擎的优化重点之一是权重缓存与复用(如使用更大的L2 Cache或优化kernel的数据复用策略)。

2.2 自回归生成:逐的序列构建

核心原理:条件概率的链式分解

自回归(Autoregressive)生成是LLM推理的基本范式。其数学本质是条件概率的链式法则:P(y1, y2, ..., yn | x) = P(y1|x) * P(y2|x, y1) * ... * P(yn|x, y1, ..., yn-1)。模型在每一步只预测下一个的概率分布,然后通过采样策略(如贪心搜索、Top-k、Top-p)选择或采样出一个,将其拼接到输入序列末尾,作为下一步的输入。这个过程循环进行,直到生成结束符(EOS)或达到最大长度。

这种逐生成方式带来了两个关键特性:顺序依赖性(第t+1个依赖于前t个的输出)和不可并行性(无法同时生成多个)。这直接导致了推理延迟的累积。

操作流程:一次完整的自回归生成

  1. 输入预处理:将用户提示词通过Tokenizer转换为 ID序列。
  2. 预填充:将整个输入序列一次性送入模型,并行计算所有输入位置的隐状态,并生成第一个输出。
  3. 循环解码:将新生成的作为输入,送入模型,计算其隐状态,并预测下一个。
  4. 终止判断:检查是否生成EOS 或达到max_new_tokens限制。

案例拆解:贪心解码与束搜索的代价

贪心解码(Greedy Decoding)每一步选择概率最高的,速度快但可能陷入局部最优。束搜索(Beam Search)维护多个候选序列(束宽=4),每一步保留概率最高的4个序列,最终选择整体概率最高的序列。束搜索的代价是计算量增加约束宽倍,且KV Cache占用也相应增加。在实际部署中,对于聊天场景,通常使用采样(Sampling)而非束搜索,因为后者容易产生重复和枯燥的文本。

风险提示:自回归生成的长度与延迟呈线性关系。当max_new_tokens设置过大时,即使输入很短,也可能导致极高的延迟和显存消耗。在生产环境中,必须设置合理的max_new_tokens上限,并监控生成长度分布。

常见误区:误以为可以并行生成多个

虽然存在“投机采样”(Speculative Decoding)或“并行解码”技术,但标准自回归生成是严格串行的。投机采样通过一个小模型先草拟多个,再由大模型并行验证,但这并未改变自回归的本质,只是通过“猜测-验证”减少了串行步数。理解这一点,才能理解为何推理引擎要引入Continuous Batching来提升吞吐量——因为单个请求的串行延迟无法缩短,只能通过并行处理多个请求来提升整体效率。

2.3 KV Cache:推理的“记忆”与显存瓶颈

核心原理:避免重复计算的缓存机制

在自回归解码的每一步,计算当前的注意力分数时,需要用到之前所有的Key(K)和Value(V)向量。如果不加缓存,每一步都需要重新计算之前所有的K和V,这将导致计算量随序列长度呈平方级增长,完全不可接受。KV Cache正是为了解决这一问题而设计的:在预填充阶段,计算并存储所有输入的K和V;在解码阶段,每生成一个新,计算其K和V并追加到缓存中,同时从缓存读取历史K和V用于注意力计算。

KV Cache的大小计算公式为:2(K和V) × 层数 × Batch Size × 序列长度 × 注意力头数 × 头维度 × 精度字节数。例如,对于Llama-2-7B(32层,32个头,头维度128),在FP16精度下,每个的KV Cache占用为 2 × 32 × 32 × 128 × 2 = 512 KB。当序列长度为4096时,单条序列的KV Cache占用高达2GB。

判断方法:显存容量规划

部署LLM时,显存占用主要由三部分构成:模型权重、KV Cache和激活值(Activations)。激活值在预填充阶段较大,但解码阶段较小。KV Cache是动态增长的,是显存规划的核心变量。推理引擎(如vLLM)通过PagedAttention将KV Cache分块管理,类似操作系统的虚拟内存分页,从而减少显存碎片,提高利用率。

模型规模权重显存 (FP16)KV Cache/4K上下文KV Cache8K上下文KV Cache
7B14 GB512 KB2 GB4 GB
13B26 GB1 MB4 GB8 GB
70B140 GB5 MB20 GB40 GB

案例拆解:KV Cache导致的显存OOM

假设我们使用单张A100-80G部署Llama-2-13B模型。权重占用26GB,预留激活值和CUDA context约4GB,剩余可用显存约50GB。如果每条请求的上下文长度为4096,则每条请求的KV Cache占用4GB。理论上最多可并发处理12条请求。但如果推理引擎没有高效的内存管理(如vLLM的PagedAttention),由于显存碎片化,实际并发数可能只有6-8条。这就是为什么推理引擎的KV Cache管理能力直接决定了其吞吐量上限。

优化实践:使用KV Cache量化(如INT8量化)可以将KV Cache占用减半,但可能带来轻微的精度损失。此外,滑动窗口注意力(Sliding Window Attention)或稀疏注意力可以限制KV Cache的增长,但会牺牲长距离依赖的建模能力。

常见误区:忽略KV Cache的显存增长

许多初次部署者只关注模型权重的大小,而忽略了KV Cache的显存占用。当并发请求增多或上下文变长时,KV Cache会迅速耗尽显存,导致OOM。正确的做法是使用推理引擎提供的显存利用率监控,并设置合理的最大并发数和最大序列长度。

2.4 预填充与解码阶段:两种截然不同的计算模式

核心原理:计算密集与访存密集的分离

LLM推理过程被清晰地划分为两个阶段:预填充(Prefill)和解码(Decode)。预填充阶段处理整个输入提示词,并行计算所有输入的隐状态,并生成第一个输出。此阶段的计算量较大,属于计算密集型(Compute-bound),GPU的算力利用率较高。解码阶段则逐生成后续内容,每一步只处理一个,但需要读取整个KV Cache和模型权重,属于访存密集型(Memory-bound),GPU的算力利用率通常很低(可能低于10%)。

这种两阶段特性对推理引擎的设计有深远影响。例如,Chunked Prefill技术将长提示词的预填充拆分为多个小块,与解码请求交错执行,以平衡GPU利用率和延迟。而Continuous Batching则是在解码阶段动态调度多个请求,让GPU始终有足够的并行工作。

判断方法:通过Profiling识别阶段切换

使用NVIDIA Nsight或PyTorch Profiler观察GPU kernel执行时间,可以清晰看到预填充阶段的长kernel(如大矩阵乘法)和解码阶段的短kernel(如小矩阵乘法、GEMV)。预填充阶段的GPU利用率通常高于50%,而解码阶段可能低于10%。推理引擎的调度器需要在这两种阶段之间平滑切换,避免GPU空闲。

案例拆解:长提示词场景下的预填充延迟

假设用户输入一篇5000字的文章(约7000个)作为提示词,要求模型进行摘要。预填充阶段需要处理这7000个,计算量约为 2 × 7000 × 4096 × 4096 × 32 ≈ 7.5 TFLOPs。在A100(FP16算力312 TFLOPs)上,理论计算时间约为24ms。但实际由于内存带宽限制和kernel启动开销,可能需要100-200ms。这个延迟(TTFT)对用户体验影响显著。推理引擎通过预填充与解码的分离调度,可以优先处理预填充请求,减少TTFT。

经验提醒:对于交互式应用(如聊天机器人),TTFT应控制在500ms以内。如果预填充延迟过高,可以考虑使用提示词缓存(Prompt Caching),将相同前缀的预填充结果缓存复用,避免重复计算。

常见误区:将两阶段视为一个整体

性能调优时,必须区分预填充和解码的指标。预填充阶段关注TTFT(Time To First ),解码阶段关注TPOT(Time Per Output )。将两者混为一谈,会导致无法准确定位瓶颈。例如,如果TTFT正常但TPOT很高,问题可能出在KV Cache访存或权重带宽上;如果TTFT很高,则可能是预填充计算量过大或GPU算力不足。

2.5 吞吐量与延迟:性能的度量衡

核心原理:系统效率与用户体验的平衡

吞吐量(Throughput)和延迟(Latency)是衡量LLM推理系统性能的两个核心指标,它们之间存在内在的权衡关系。吞吐量通常定义为系统在单位时间内生成的总数(tokens/s),反映了系统的整体处理能力。延迟则分为两种:TTFT(首延迟,从请求发出到收到第一个的时间)和TPOT(每输出延迟,后续每个的生成间隔)。对于流式输出,TPOT直接决定了用户感知的生成速度。

高吞吐量意味着系统可以服务更多并发请求,但通常会增加单个请求的延迟(因为需要排队和共享计算资源)。低延迟则提供更好的交互体验,但可能牺牲系统的整体利用率。推理引擎的核心目标就是在满足延迟约束(SLA)的前提下,最大化吞吐量。

判断方法:性能基准测试

进行性能测试时,需要明确测试场景:并发数、输入/输出长度分布、请求到达率。常用的基准测试工具包括LLMPerf、vLLM的benchmark脚本等。关键指标包括:

  • 吞吐量:总生成数 / 总耗时(包括排队和生成时间)。
  • TTFT:所有请求的TTFT平均值或P99值。
  • TPOT:所有请求的TPOT平均值或P99值。
  • 端到端延迟:从请求发出到完整响应接收的总时间。
场景优化目标关键指标典型约束
在线聊天低延迟TTFT < 500ms, TPOT < 50ms并发数 < 100
离线批量处理高吞吐吞吐量 > 1000 tokens/s延迟无硬性要求
代码生成平衡TTFT < 1s, TPOT < 100ms并发数 < 50

案例拆解:通过Continuous Batching提升吞吐量

假设一个推理引擎采用静态批处理(Static Batching),必须等待一个批次的所有请求都生成完毕后,才能处理下一批请求。如果批次中有请求生成长度差异大,短请求会等待长请求,导致GPU利用率下降。而Continuous Batching(连续批处理)允许在批次中动态添加和移除请求:当一个请求生成完毕,立即将其移出批次,并加入新的请求。这样GPU始终在处理活跃的请求,显著提升了吞吐量。vLLM、TensorRT-LLM等引擎均实现了此机制。

在一个实际测试中,使用Llama-2-7B模型,输入长度128,输出长度256,并发32个请求。静态批处理的吞吐量约为800 tokens/s,而Continuous Batching的吞吐量可达1500 tokens/s,提升近一倍。但代价是单个请求的TPOT可能略有波动(因为需要与其他请求共享GPU资源)。

风险提示:过度追求吞吐量会导致TPOT显著上升,影响用户体验。在生产环境中,必须设置延迟SLA(如TPOT P99 < 100ms),并通过负载均衡和请求排队策略来保证SLA。

常见误区:只关注吞吐量而忽略延迟分布

平均延迟可能掩盖长尾问题。P99延迟(即99%的请求延迟低于该值)是更重要的指标。在推理引擎中,由于调度和资源竞争,P99延迟可能远高于平均值。性能调优时,应同时关注平均值和P99/P95值,并分析延迟分布直方图。

总结复盘:本章的核心在于建立“两阶段-一缓存-双指标”的分析框架。预填充阶段是计算密集的,解码阶段是访存密集的,KV Cache是连接两阶段的桥梁,也是显存优化的主战场。吞吐量和延迟是衡量系统性能的最终标准,它们之间的权衡是推理引擎设计的核心矛盾。理解这些概念后,我们才能深入理解后续章节中vLLM的PagedAttention、TensorRT-LLM的图优化、SGLang的RadixAttention等高级特性,它们本质上都是对这一基础框架的工程优化。