{* YBB Header v4.0 — Alpine.js + 自定义 CSS *}

引言:为什么推理是 LLM 落地的核心瓶颈

2024年至2026年间,大语言模型的能力边界不断被刷新,从百万级到千万级参数的模型层出不穷。然而,在实验室的 benchmark 数字背后,真正的挑战在于:如何让这些庞大模型在有限的硬件资源下,以可承受的成本、足够快的速度服务真实用户。训练一颗强大的大脑固然困难,但让这颗大脑持续、稳定、高效地思考,同样是一门精深的工程学问。

推理优化是一个横跨计算机体系结构、数值计算、分布式系统、编译原理等多个领域的综合性课题。本文将从 LLM 推理的独特计算特征出发,深入剖析 KV Cache 机制、推测解码(Speculative Decoding)、模型量化与压缩、PagedAttention 内存管理、连续批处理(Continuous Batching)等核心技术,并以 vLLM 和 TensorRT-LLM 为典型案例,展示如何将这些技术组合应用于生产级部署。

第一节:理解 LLM 推理的计算特征

1.1 自回归生成的本质矛盾

大语言模型的核心工作方式是自回归(Autoregressive):逐个 token 生成输出,每个 token 的生成都需要完整的前序 token 作为上下文。这一模式造成了 LLM 推理的两大独特挑战:

挑战一:内存带宽自瓶颈(Memory-Bound)。在生成阶段,模型需要将所有参数从 HBM(高带宽内存)加载到 GPU 计算单元。对于 70B 参数的 FP16 模型,单次推理需要加载 140GB 参数。以 H100 的 3.35TB/s 内存带宽计算,仅加载参数就需要约 42ms,这意味着理论上限约为 24 tokens/s。计算单元大部分时间在等待数据搬运,而非实际计算。

挑战二:序列长度动态变化。不同请求的输入输出长度差异巨大。一条简短问答可能只需 20 tokens,而一篇长文总结可能需要 4000+ tokens。传统静态批处理(Static Batching)会导致大量计算和内存浪费。

1.2 预填充与解码的分离

LLM 推理通常分为两个阶段:

预填充阶段(Prefill Phase):一次性处理全部输入 prompt,为每个 token 计算 KV 向量,存入 KV Cache。这一阶段是计算密集(Compute-Bound)的,GPU 利用率接近峰值,可并行处理整个输入序列。

解码阶段(Decode Phase):逐个生成输出 token。每次只新增一个 token 的 KV 向量到 Cache 中,并从 Cache 中读取全量 KV 向量计算注意力。这一阶段是内存带宽密集(Memory-Bound)的,传统方法每次只处理有效数据的一小部分,GPU 利用率极低,通常不到 15%。

理解这两个阶段的本质差异是掌握一切推理优化技术的基础。预填充阶段需要的是原始算力,解码阶段需要的是内存带宽和高效的 KV 缓存管理。

第二节:KV Cache 机制深度解析

2.1 KV Cache 的工作原理

在 Transformer 的注意力机制中,每个 token 都需要与所有前序 token 计算注意力分数。如果不做缓存,每次生成新 token 都需要重新计算所有历史 token 的 Key 和 Value 向量,复杂度为 O(n²)。

KV Cache 的思路十分直接:每个 Transformer 层的注意力计算完成后,将该层所有 token 的 Key 和 Value 向量保存下来。生成新 token 时,只需计算新 token 的 K、V 向量,追加到 Cache 末尾,然后使用新 token 的 Query 与全部 Cache 中的 Key 计算注意力。

数学上,第 t 步生成可表示为:

Attention(Q_t, K_{1:t}, V_{1:t}) = softmax(Q_t · K_{1:t}^T / √d) · V_{1:t}

其中 Q_t 是新 token 的 Query,K_{1:t} 和 V_{1:t} 是从 KV Cache 中读取的全部历史向量。

2.2 KV Cache 的内存占用分析

KV Cache 的内存消耗是 LLM 推理中最主要的内存开销之一。以 LLaMA-2-70B 模型为例:

单层 KV 大小 = 2(K和V)× seq_len × num_kv_heads × head_dim × dtype_size
           = 2 × seq_len × 8 × 128 × 2 bytes(FP16)
           = seq_len × 4096 bytes
           = seq_len × 4 KB

模型总层数 = 80 层
总 KV Cache = 80 × seq_len × 4 KB = seq_len × 320 KB

对于一个 4096 token 的序列,单个请求的 KV Cache 就需要约 1.3GB 显存。在 A100 80GB 的显存中,除去模型参数本身 140GB(即使 FP16 也需要 140GB,实际需多张卡),KV Cache 成为决定最大批处理量和并发能力的关键因素。

2.3 KV Cache 的精度优化

在实践中,KV Cache 的精度可以适当降低:

FP16 → FP8:NVIDIA H100/B200 原生支持 FP8 计算,KV Cache 也可降为 FP8 存储,内存减半。研究表明,KV Cache 从 FP16 降为 FP8 对生成质量的影响可以忽略不计(困惑度差异 < 0.1%),这使得在同等硬件下可支持的序列长度翻倍。

KV Cache 量化:对于更激进的内存节省,可以对 KV Cache 进行分组量化(Group Quantization)。例如,按头维度分组,每组使用独立的 scale 和 zero-point。INT4 量化可将 KV Cache 降至原来的 1/4,但通常需要配合 GQA(Grouped Query Architecture)和 fine-grained 量化策略来保持质量。

第三节:PagedAttention —— 革命性的 KV Cache 管理

3.1 传统连续分配的痛点

在 PagedAttention 出现之前,推理引擎为每个请求预分配一块连续的 GPU 显存块来存储 KV Cache。这种方法存在严重的内存浪费:

预分配浪费:为保证长序列能容纳,系统按最大长度(如 4096 tokens)预留空间,但大多数实际请求远短于此。实测中,平均有效利用率仅 20%-40%。

内部碎片:由于不同请求的序列长度不同,预分配的固定大小块体造成大量内部碎片。

外部碎片:并发请求的动态创建和释放会在显存中留下不连续的空闲区域,进一步降低可用内存总量。

3.2 PagedAttention 的设计思想

vLLM 团队提出的 PagedAttention 借鉴了操作系统中虚拟内存和分页管理的思想,将 KV Cache 的连续分配转变为分页管理:

分页存储:将每个请求的 KV Cache 切分为固定大小的 block(通常 16 tokens 的 KV 向量),不再要求显存连续。一个请求的各个 block 通过 block table 串联,就像操作系统的页表一样。

按需分配:仅在需要时分配新 block,消除了预分配浪费。实例显示,内存利用率从传统方法的 20%-40% 提升至接近 100%。

零碎片:由于所有 block 大小相同,不存在外部碎片。任何空闲 block 都可被任何请求使用。

共享与 Copy-on-Write:在多轮对话、Beam Search 或 Parallel Sampling 场景中,多个序列可以共享前缀的 KV Cache block。当某个序列需要修改共享 block 时,执行 Copy-on-Write。这一特性在系统提示(System Prompt)共享场景中尤为重要。

3.3 PagedAttention 的实现细节

在 CUDA 层面,PagedAttention 需要自定义高效的 Attention kernel,能够从分散的 block 中随机读取 KV 向量。关键优化包括:

块表查找的合并:将 block table 常驻在 L2 Cache 中,减少 DRAM 访问。

Bank Conflict 避免:对 block 内部的数据布局进行 padding,避免 shared memory bank conflict。

与 Tensor Core 协同:利用 H100 的 Tensor Core 加速分页矩阵运算。在 A100 上,PagedAttention 实现了 24 tokens/s 的单请求解码速度,比传统方法提升 2-4 倍。

第四节:推测解码(Speculative Decoding)

4.1 核心思想:用小模型打前站

推测解码是近年来最具突破性的 LLM 推理加速技术之一。其核心思路利用了 LLM 推理的一个关键特征:简单 token 的生成比困难 token 更容易预测。

具体方法:使用一个小型但快速的自回归模型(Draft Model)作为"探路者",连续预测一批候选 token(通常 5-8 个),然后用大型目标模型(Target Model)并行验证这些候选 token。由于验证阶段可以并行处理所有候选 token,而 Draft 模型的参数远小于 Target 模型,即使需要丢弃部分错误候选,整体吞吐量仍然显著提升。

4.2 算法流程

推测解码的完整流程如下:

步骤 1:小模型推测。Draft Model(如 700M 参数)连续自回归生成 γ 个 token。这些 token 被作为候选序列。

步骤 2:大模型并行验证。Target Model(如 70B 参数)一次性并行处理整个候选序列(加上原始前缀),得到每个位置的概率分布。注意,这一步是并行执行的,而非逐 token 串行。

<步骤 3:接受/拒绝采样。对每个候选位置 i,比较 Target Model 和 Draft Model 的概率分布:

  • 以概率 min(1, p_target(x_i)/p_draft(x_i)) 接受该 token
  • 若被拒绝,从调整后的分布 max(0, p_target(x_i) - p_draft(x_i)) 重新采样一个 token
  • 后续候选全部丢弃

步骤 4:剩余追加。如果全部 γ 个 token 都被接受,额外从 Target Model 的分布中采样下一个 token(因为 Target Model 的最后一个位置也产出了一个有效预测)。

4.3 加速效果分析

推测解码的加速倍率取决于两个因素:Draft Model 与 Target Model 的速度比、候选接受率 α。

以 700M Draft Model 搭配 70B Target Model 为例:

  • Speed Ratio:小模型约为大模型速度的 11 倍(与参数量成反比)
  • Acceptance Rate α:通常 0.6-0.85,取决于任务类型和小模型匹配度
  • 期望接受数 E[accepted] = (1 - α^{γ+1}) / (1 - α),对 α=0.8, γ=5 约 3.66 tokens
  • 净加速约 2-3 倍,Token 生成速率从 24 tokens/s 提升至 50-70 tokens/s

4.4 变体和扩展

SpecInfer(树状推测):不再使用线性链式推测,而是构建一棵推测树。多个独立的 Draft 模型并行生成不同分支,Target Model 使用 Tree Attention 并行验证整棵树,接受所有符合一致性约束的路径上的 token。理论上可进一步提升接受数。

Medusa(多头推测):在 Target Model 上附加多个轻量级的预测 Head,每个 Head 负责预测不同未来位置的 token。这些 Head 是大模型的顶层网络,不需要独立的 Draft Model,因此部署更简洁。每个 Medusa Head 额外仅需约 0.1% 参数量。

EAGLE( EagleAttention):使用 Target Model 倒数第二层的特征作为输入,训练一个轻量级的自回归模型来生成候选。由于直接利用了目标模型的内部表示,EAGLE 的接受率更高(通常 >0.85),且结构更简单。

第五节:模型量化与压缩

5.1 量化对推理的影响

模型量化是减少内存占用、提高推理吞吐量的最直接手段。从 FP16 到 INT8,模型体积减半,内存带宽需求减半;从 INT8 到 INT4,再减半。量化技术的关键在于:如何用更少的比特表达尽可能不损失精度的数值。

LLM 的权重和激活值分布具有明显特征:存在大量接近零的小值,同时少量参数/激活值是量级远大于均值的 outlier。均匀量化在处理这些 outlier 时会引入显著误差。

5.2 GPTQ:基于优化的训练后量化

GPTQ 是最经典的 LLM 训练后量化方法之一,属于二阶量化方法:

工作原理:逐层量化,使用未量化模型的 Hessian 矩阵信息指导量化过程。对于每一层权重 W,GPTQ 按列迭代处理:量化当前列后,使用未量化的其余列来补偿因量化引入的误差。

量化精度:GPTQ 支持 4-bit、3-bit 甚至 2-bit 量化。4-bit GPTQ 通常能将困惑度增加控制在 1% 以内。

推理优化:推理时,INT4 权重需要在 GEMM 计算中反量化为 FP16。为了高效利用 Tensor Core,GPTQ kernel 将反量化融合在矩阵乘法中,通过查表法(lookup table)避免分支判断。

5.3 AWQ:激活感知的权重量化

AWQ(Activation-Aware Weight Quantization)的发现是:并非所有权重同等重要。对应较大激活值的权重通道(Salient Weights)对模型输出影响更大。

AWQ 的做法是对这些重要权重通道给予更高精度(或完全不量化),对不重要的通道进行激进的 4-bit 量化。具体实现是通过搜索每个输入通道的缩放因子(per-channel scaling),在量化前对高重要性的权重行进行放大,使其在反量化后恢复原值。

AWQ 在 4-bit 量化的质量通常优于 GPTQ,且推理速度更快(不需要额外的补偿计算),已成为 vLLM、TensorRT-LLM 和 llama.cpp 默认支持的量化方案之一。

5.4 FP8 与硬件原生支持

NVIDIA H100/B200 GPU 原生支持 FP8 Tensor Core 计算。FP8 提供两种格式:E4M3(4位指数 3位尾数,精度高)和 E5M2(5位指数 2位尾数,范围大)。

混合精度推理:前向传播使用 FP8 计算 GEMM,但 Normalization 和 Attention 的 softmax 仍使用 FP16 以保证数值稳定性。

实验结果:在 H100 上运行 FP8 的 LLaMA-3-70B 推理,性能比 FP16 提升约 1.5-1.7 倍,而质量几乎无损失。这是目前性价比最高的量化部署路径之一,前提是硬件支持。

5.5 GGUF 格式与 llama.cpp 生态

llama.cpp 项目及其 GGUF 格式在开源社区中产生了深远影响。GGUF 支持从 2-bit 到 8-bit 的多种量化粒度,包括:

  • Q4_K_M:4-bit 量化,中等质量级别
  • Q5_K_M:5-bit 量化
  • Q6_K:6-bit 量化,接近 FP16 质量
  • Q8_0:8-bit 量化,无损级别

CPU-offloading 是 llama.cpp 的另一个杀手级特性:将模型的层部分或全部卸载到 CPU 内存,GPU 只处理热点层。虽然速度不如 GPU 推理,但使得在消费级硬件上运行 70B 模型成为可能。

第六节:并行策略与分布式部署

6.1 张量并行(Tensor Parallelism)

张量并行将模型的每一层按行或列切分到多个 GPU 上。以 Multi-Head Attention 为例,不同 GPU 计算不同注意力头的结果,最后通过 AllReduce 聚合。FFN 层可按列切分权重矩阵,对应通过 AllReduce 聚合输出。

优势:通信量小(每层只需要一次 AllReduce),负载均衡好。在 NVLink 拓扑(如 A100 的 600GB/s 互联)下效率极高。

劣势:每张 GPU 需要存储全部 KV Cache,对显存要求不降反增。且跨节点通信受 InfiniBand 带宽限制。

6.2 流水线并行(Pipeline Parallelism)

流水线并行将模型的不同层分配到不同 GPU。GPU 0 处理前 N 层,GPU 1 处理接下来 N 层,以此类推。不同请求在不同 stage 之间像流水线一样流动。

Micro-batching:为减少流水线气泡(bubble),将 batch 拆分为多个 micro-batch 在不同 stage 间交错执行。例如 4 级流水线中,当 stage 1 正在处理 micro-batch 3 时,stage 4 可以输出 micro-batch 0 的结果。

6.3 混合并行策略

在生产级部署中,通常会组合使用多种并行策略:

  • 节点内张量并行:利用高速 NVLink 最大化单节点算力
  • 跨节点流水线并行:通过 InfiniBand 连接不同节点
  • 数据/序列并行:同一模型的多个副本并行处理不同请求,提升在线服务水平

以部署 Meta Llama-4-Maverick(400B MoE)为例,Meta 使用 8×H100 节点进行节点内张量并行,再通过跨节点流水线并行为每个请求提供服务。DeepSeek-V3 的 671B 参数则需要更多节点协同工作。

第七节:vLLM 架构与生产实践

7.1 vLLM 核心架构

vLLM 已成为开源 LLM 推理部署的事实标准,其核心设计围绕 PagedAttention 展开:

调度器(Scheduler):实现连续批处理(Continuous Batching / Iteration-Level Scheduling)。不再等待整个 batch 完成才添加新请求,而是在每次 decode iteration 结束后动态调整 batch 组成。首批正在生成较长输出的请求不会阻塞新到达的短请求。

KV Cache Manager:管理 GPU 和 CPU 的 block 分配。当 GPU KV Cache 不足时,将低频使用的 block swap 到 CPU 内存,需要时再 swap 回来。

Prefill-Decode Disaggregation(PD 分离):vLLM v0.6+ 支持将 Prefill 和 Decode 分配到不同的 GPU 资源池。Prefill 需要大量算力,可使用 Tensor Parallelism 加速;Decode 需要大内存带宽,适合单独部署。通过高速网络(NVLink/RoCE)传输 KV Cache 实现解耦。

7.2 TensorRT-LLM 的工业级实现

NVIDIA 的 TensorRT-LLM 提供了另一种高性能推理路径:

In-flight Batching:类似连续批处理,支持动态 batch 调整。

GEMM 与 Attention 融合:将矩阵乘法与 Attention 计算融合为单一 kernel,减少中间数据的读写开销。

Custom CUDA Kernels:针对 NVIDIA GPU 架构高度优化的 kernel 实现,包括 FlashAttention、Fused MLP(Dense + GEMM 一行完成)等。

FP8 + 量化直接路径:TensorRT-LLM 直接支持 FP8 和多种 INT 量化格式,无需额外工具链。

7.3 部署选型指南

选择 vLLM 的场景:

  • 需要快速启动,支持多种模型架构(HuggingFace 格式直接加载)
  • 需要灵活的功能开关(如 speculative decoding、prefix caching、prompt lookup decoding)
  • 开源生态活跃,社区修复 bug 速度快
  • 适合中小规模部署和研发实验

选择 TensorRT-LLM 的场景:

  • 需要榨取极致的硬件性能(尤其是 NVIDIA H100/B200)
  • 有专门的优化工程师团队进行模型编译和调优
  • 与 Triton Inference Server 深度集成的企业级生产环境

第八节:前沿趋势与挑战

8.1 Sparse Attention 与长上下文

随着上下文窗口扩展到 100K+ tokens,标准 O(n²) Attention 的计算代价变得不可接受。Sparse Attention 只对关键位置计算全量注意力:

Mixture of Memory(MoM):在 InfiniAttn 中提出,将 KV Cache 分为局部窗口、压缩摘要和全局锚点三类,动态选择每个 Query 关注哪些 Key。

Ring Attention:将超长序列分布式切分到多个设备上,各设备通过环形通信依次将 KV 传递给下游,仅保留本地片段的 Cache。Google Gemini 1.5 的 100 万 token 上下文即采用此类技术。

8.2 分布式推断与边缘部署

拆分推断(Split Inference):将 Transformer 的浅层放在客户端设备(手机/PC),深层通过 API 在云端执行。在用户输入简单请求时(可被浅层缓存覆盖),甚至不需要访问云端。

模型卸载(Offloading):结合 CPU RAM 甚至 NVMe SSD 存储模型参数,在推理时按需加载到 GPU。GGUF + llama.cpp 已能实现这一模式,使得老旧 GPU 甚至集成显卡也能运行 13B 级别的模型。

8.3 推测解码与训练框架协同

推测解码的成功揭示了一个更广阔的方向:LLM 推理不一定必须从纯文本前缀出发。未来系统可能会结合:

  • 结构化的模板预测:利用 prompt template 预知下一部分结构(如 JSON schema)
  • 程序辅助推断:让 LLM 先输出代码框架,再用确定性代码填充细节
  • 多模态跨域预测:用视觉特征辅助文本生成,或反之

结语

LLM 推理优化是一个快速发展的多层级技术栈。从底层的 GPU kernel 优化到中层的内存管理策略,再到顶层的分布式对齐与负载均衡,每一层都对最终性能有显著影响。

站在 2026 年的视角,我们正处在一个有趣的转折点:硬件进步让更大模型成为可能(H200、B200 的 HBM 容量达 141GB),同时优化技术让同等硬件可以服务更多请求。两者共同推动 LLM 应用的成本持续下降和体验持续提升。

对于从业者而言,理解这些优化技术的原理比单纯堆砌参数更重要。因为今天的"不可能",可能就是明天的"标配"。正如三年前的 175B 模型还需要集群部署,今天 7B 的模型已能在手机上运行——技术的本质就是将今天的极端需求,变成明天的日常体验。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部