⚡ 深度技术

LLM 推理优化技术
深度解析

📅 2026-05-20 ⏱️ 阅读约 18 分钟 👤 系统架构组

从算法层面到工程实现,全面剖析大语言模型推理加速的核心技术。涵盖 Continuous Batching、KV Cache 管理、量化策略、PagedAttention 原理以及 VLLM 整体架构设计,适合高级工程师和架构师参考。

1. 背景与挑战

为什么 LLM 推理如此昂贵?

大语言模型(LLM)推理与传统 ML 推理有本质区别。其核心挑战在于两个维度:计算密集度内存带宽压力。以 GPT-3 175B 为例,单次前向传播需要约 350 TFLOPS 的计算量,而权重体积接近 350 GB,即使在 A100 80GB 卡上也需要多卡并行才能装载。

推理分为两个阶段:

  • Prefill 阶段:处理输入 Prompt,并行计算,计算密集型。
  • Decode 阶段:逐 Token 自回归生成,矩阵向量乘法,内存带宽密集型

Decode 阶段是瓶颈所在。每次生成一个 Token 都需要将完整权重矩阵与当前隐藏状态相乘,而自回归特性导致大量中间结果(KV Cache)被反复访问。未经优化时,Decode 的 Token 生成速度往往低于 10 tokens/s,无法满足在线服务 50+ tokens/s 的体验要求。

核心优化方向

📦

内存优化

通过 KV Cache 复用已计算结果,避免重复计算;PagedAttention 分块管理缓存,提升内存利用率。

计算优化

Continuous Batching 打破静态批次限制,提升 GPU 利用率;算子融合减少内存访问开销。

🔢

精度优化

量化技术(W8A16、FP8 等)以精度换算力,大幅降低内存占用和计算延迟。

🔧

架构优化

Disaggated Prefill-Decode、投机解码、KV Cache 分布式管理,适应生产环境复杂调度需求。

2. Continuous Batching

动态批处理:从静态到自适应的请求调度

2.1 传统 Static Batching 的局限性

传统 Batching 将多个请求打包成一个批次并行处理,理论上可充分利用率。但 LLM 自回归生成天然存在生成长度不一致的问题——批次中某个请求先行结束时,其他请求仍在运行,导致 GPU 资源长时间空转。

一个批次中,最长序列拖累了整个批次的完成时间,实际 GPU 利用率通常低于 30%。

— Orca: Fine-Grained Reactive Batching, 2022

2.2 Iteration-Level Scheduling

Continuous Batching(又称 Iteration-Level Batching)的核心思想是:以 iteration(每次 Token 生成)为调度粒度,而非以请求为粒度。每个 iteration 结束后,立即释放已完成的序列所占槽位,并插入新的请求填补空缺。

请求 A [256 tokens]
请求 B [128 tokens]
请求 C [512 tokens]
→ Prefill → Decode × N → 🔄 动态插队
B 完成 → 释放
新请求 D 入队

2.3 实现细节

Continuous Batching 需要解决三个关键问题:

  • 序列长度追踪:记录每个请求已生成的 Token 数和最大长度,动态计算剩余步数。
  • 槽位管理:预分配固定数量的 Sequence Slot,运行时通过 Slot Map 维护"请求 → Slot"的映射关系。
  • 抢占与调度策略:新请求到达时,若无空闲 Slot,需决定是否抢占(Abort)低优先级长序列。
Pythonseudocode
# Simplified Continuous Batching loop (pseudocode)
def scheduler_step(running_seqs, pending_seqs, engine):
    # 1. Collect finished sequences from last step
    finished = [s for s in running_seqs if s.is_done()]
    for seq in finished:
        seq.free_slots()     # Release memory
        running_seqs.remove(seq)

    # 2. Fill freed slots with pending requests
    free_slots = get_free_slots(running_seqs)
    while pending_seqs and free_slots:
        new_seq = pending_seqs.pop(0)
        new_seq.assign_slots(free_slots.pop())
        running_seqs.append(new_seq)

    # 3. Run one step for all running sequences
    engine.step(running_seqs)   # Single kernel launch

2.4 性能收益

指标Static BatchingContinuous Batching提升
GPU 利用率20–40%60–85%~2x
Throughput (req/s)Baseline3–5x ↑3–5x
P99 Latency高(被长序列阻塞)显著降低显著
内存利用率低效碎片化高效紧凑高效

3. KV Cache

自回归模型的核心瓶颈——如何避免重复计算?

3.1 问题本质

在 Transformer 的自注意力机制中,每个 Token 在生成下一个 Token 时,都需要 attend 到此前所有 Token 的 Key 和 Value 向量。标准实现会在每一步重复计算这些 K/V,完全浪费了已计算过的结果。

以 LLaMA-2 70B 为例:

  • 每层 attention 都有 80 GB 权重(Q/K/V/O 投影)
  • Prefill 阶段:处理 2048 tokens,约需计算 2048 × 2048 的 attention 矩阵
  • Decode 阶段:每步只需计算 1 × 2048 的 attention,但若重复加载 80 GB 权重,带宽成为瓶颈

3.2 KV Cache 机制

KV Cache 的核心思想是:为每个序列维护一个缓存区,将各层 attention 计算出的 K/V 向量持久化存储,后续生成步骤直接查询缓存,无需重新计算。

Input Token
Q = W_q × input
Cache[K,V] += [K,V]
Attention(Q, Cache[K,V])

3.3 分层 KV Cache

KV Cache 按层分布存储于 GPU HBM 或 CPU DRAM 中。现代推理引擎(如 vLLM)通常将 KV Cache 划分为多个 Block,以 Block 为单位进行管理,支持不规则长度的序列并实现高效的内存分配。

Python
# KV Cache logical layout in vLLM
# Each sequence occupies a list of KV Blocks (physical)

class KVCache:
    # Logical view: seq -> [block_ids]
    seq_blocks: Dict[int, List[int]]

    # Physical view: block_id -> PagedAttention block
    # Stored in pinned CPU memory or GPU HBM
    blocks: List[Block]

# When generating token t+1 for sequence s:
# 1. Read K_t, V_t from block(s) — zero-copy via PagedAttention
# 2. Compute attention(Q_t, cache[K_0:t, V_0:t])
# 3. Write new K_{t+1}, V_{t+1} to next free position in block

3.4 显存估算与限制

模型参数量FP16 KV Cache/Token1000 tokens 显存最大并发(L40 48GB)
LLaMA-2 7B7B~0.5 MB~500 MB~80 concurrent
LLaMA-2 70B70B~4 MB~4 GB~10 concurrent
GPT-4 (approx)~1.8T MoEvariablevariesvery limited

3.5 MQA / GQA 的辅助优化

Multi-Query Attention (MQA) 和 Grouped Query Attention (GQA) 通过让多个 Query 头共享同一组 K/V 头,将 KV Cache 体积减少为原来的 1/N(对于 N 组 Query 头),是 KV Cache 管理的重要辅助手段。

4. 量化技术

精度与速度的权衡:从 FP32 到 FP8 的完整技术图谱

4.1 量化基本原理

量化(Quantization)通过将 FP32/FP16 权重和激活值映射到低位宽整数来表示,在保持模型能力的同时大幅降低内存占用和计算成本。

核心公式:

Y_quant = round(Y_fp32 / s) + z
其中 s 为缩放因子(scale),z 为零点(zero-point,用于对称/非对称量化)。

4.2 W8A16 量化

W8A16 = Weight 8-bit + Activation 16-bit。这是目前生产环境最主流的量化方案,因为:

  • 权重压缩 50%(FP16 → INT8),KV Cache 和模型权重内存占用减半
  • 激活值保持 FP16,精度损失极小,BERT 时代大量实践验证
  • 计算时权重需要 dequant 回 FP16再做矩阵乘法(A16),而非直接做 INT8×INT8 GEMM
FP16 Input activation W8A16 Quantize GEMM FP16 compute Dequantize INT8→FP16 Out FP16 Tensor Compute Result

4.3 FP8 量化

FP8(Float 8)是 NVIDIA H100/H200 系列引入的新格式,在 Hopper 架构中提供原生硬件支持。相比 INT8,FP8 保留了浮点数的动态范围表示能力,对大语言模型这种对数值分布敏感的任务更友好。

格式存储格式动态范围精度(尾数位)适用场景
E4M3 (FP8) 1 sign + 4 exp + 3 mant 448 (max) ~3 bits mantissa Weights & Activations 前向传播
E5M2 (FP8) 1 sign + 5 exp + 2 mant 57344 (max) ~2 bits mantissa Gradients 反向传播(需要更大动态范围)

FP8-E4M3 的动态范围约为 BF16 的 1/16,但精度更高。在 LLaMA-2 70B 上,使用 FP8 推理相比 BF16 可获得 1.5–2x 的吞吐量提升,困惑度损失通常小于 0.5%。

— FP8 Formats for Deep Learning, NVIDIA, 2023

4.4 W8A8 量化(INT8×INT8)

W8A8(Weight 8-bit + Activation 8-bit)是最激进的量化方案,需要在 INT8 精度下完成矩阵乘法。这要求硬件支持 INT8 Tensor Core(如 NVIDIA Ampere 及以上),并且需要在线量化(Per-Tensor 或 Per-Token Scale)而非静态离线标定。

主要挑战:

  • Activation 动态范围大:不同层、不同 token 位置的激活值分布差异显著,需要 per-token 或 per-channel 的动态缩放。
  • 精度恢复:通常需要配合 SmoothQuant、AWQ 等校准技术,迁移异常值到权重侧。
  • 推理框架支持:目前只有 TensorRT-LLM、vLLM(实验性)等少数框架完整支持。

4.5 量化方案横向对比

方案精度损失加速比显存节省生产可用性
FP16 (Baseline)1x★★★★★
W8A16<0.5%1.5–2x~50%★★★★★
FP8 (E4M3)0.5–1.5%1.5–2x~50%★★★★
W8A8 (INT8)1–3%2–4x~60%★★★
W4A16 (INT4)2–5%3–6x~75%★★★
W4A85–10%+4–8x~80%★★

5. PagedAttention

操作系统级内存管理思想在 LLM 推理中的应用

5.1 背景:KV Cache 的内存碎片化问题

传统推理系统为每个请求预分配连续的 GPU 内存区域存储 KV Cache。然而:

  • 不同请求的目标输出长度差异巨大(从 100 到 2000 tokens 不等)
  • 预先分配的连续内存往往远大于实际使用量,造成大量内部碎片
  • 若实际长度超出预分配,则无法处理(OOM 或被截断)

5.2 核心思想

PagedAttention 借鉴了操作系统虚拟内存的 分页(paging) 机制:将 KV Cache 表示为一系列固定大小的"物理块"(physical blocks),逻辑上连续的 token 序列可以跨越多个不连续的物理块存储。

类似于进程访问虚拟地址空间时无需关心物理页的实际物理位置,PagedAttention 让每个序列在逻辑上拥有连续完整的 KV 缓存空间,按需映射到分散的物理块。

Logical KV Cache Seq A: tokens 0–1023 Seq B: 0–511 Seq C: 0–1023 Seq D Physical GPU Memory Blk 0 Blk 1 Blk 2 Blk 3 Blk 4 Blk 5 Blk 6 Blk 7 ... Blk N (free) Block Table: Seq → [physical_blocks] A: 0,1 B: 2 C: 3,4,6 D: 5

5.3 零拷贝注意力计算

PagedAttention 在执行 attention 时,通过 block_table 将逻辑 token 位置映射到物理块,GPU kernel 可以直接 gather 对应物理块中的 K/V 数据,无需内存拷贝。这使得:

  • 内存利用率提升至 90%+(传统方式约 30–50%)
  • 支持 Prefix Caching:相同前缀的请求共享物理块,避免重复存储
  • 序列可以动态扩展,直到物理内存耗尽

5.4 Prefix Caching

在实际部署中,多个请求往往共享相同的 System Prompt 或 RAG 上下文。PagedAttention 的 Block Table 机制天然支持KV Cache 共享:相同前缀的 Block 可被多个序列引用,Prefix 部分无需重新计算。

C++ / CUDA
// PagedAttention kernel pseudocode
// each thread block processes one sequence in the batch
__global__ void paged_attention_kernel(
    float* out,             // [num_seqs, num_heads, max_len, head_dim]
    const float* q,         // query
    const float* k_cache,   // physical block stored K
    const float* v_cache,   // physical block stored V
    const int* block_table, // [num_seqs, num_blocks_per_seq]
    int block_size
) {
    // 1. Get which physical blocks hold K/V for this seq
    int seq_len = ...;
    int num_blocks = (seq_len + block_size - 1) / block_size;

    // 2. Iterate over blocks, compute partial attention
    for (int i = 0; i < num_blocks; i++) {
        int physical_block_id = block_table[seq_idx * max_blocks + i];
        // Zero-copy: fetch K/V directly from k_cache/v_cache
        const float* k_block = get_block_base(k_cache, physical_block_id);
        const float* v_block = get_block_base(v_cache, physical_block_id);
        // Compute partial attention and accumulate...
        attention_partial(out, q, k_block, v_block, block_size);
    }
}

6. VLLM 架构

从请求接收到 Token 输出的完整系统设计

6.1 整体架构

VLLM 是一个端到端的 LLM 推理引擎,其核心设计目标是在有限的 GPU 显存中最大化吞吐量和降低延迟。架构分层如下:

LLM Application / API Server Scheduler (Continuous Batching) 迭代级调度 · 动态批处理 · 抢占/恢复 Model Executor (TP/PP/EP) Tensor Parallel · Pipeline Parallel · Expert Parallel KV Cache Manager (PagedAttention) Block Table · 物理块分配 · Prefix Caching Worker 0 … Worker N-1 Block Pool (GPU HBM / CPU DRAM) GPU (A100 / H100 / L40s) Weights (quantized) + KV Cache Blocks + CUDA Kernels ← Requests (OpenAI API) ← Token Output →

6.2 核心组件

① Scheduler(调度器)

Scheduler 维护 Running Sequences 和 Waiting Sequences 两个队列。每次 iteration:

  1. 检查已完成序列,触发回调并释放资源
  2. 将 Waiting 队列中的请求移入 Running(按到达顺序 FIFO)
  3. 计算当前批次的最大 sequence length,对齐到 block boundary
  4. 调用 Model Executor 执行一步前向传播

② KV Cache Manager(PagedAttention 实现)

基于 Block Manager 实现,负责:

  • 物理块的分配与回收(reference counting)
  • Block Table 维护:记录每个序列的逻辑→物理映射
  • Copy-on-Write:当多个序列共享相同前缀时,通过引用计数管理
  • evicted blocks 的 CPU offload(当 GPU 显存不足时)

③ Model Executor(模型执行器)

支持三种并行策略的组合:

  • Tensor Parallel (TP):单层内按 head 维度切分,适合单节点多卡
  • Pipeline Parallel (PP):按层切分,适合多节点扩展
  • Expert Parallel (EP):针对 MoE 架构,多专家分布在不同卡

6.3 Prefill-Decode Disaggregation

生产级 VLLM 部署中,常将 Prefill 和 Decode 阶段拆分到不同批次甚至不同硬件:

Prefill 请求
Prefill Engine
计算密集·高优先级
Decode 请求
Decode Engine
访存密集·高吞吐

原因:Prefill 阶段的计算特性和延迟目标与 Decode 截然不同,混合调度会导致互相干扰。Disaggregation 允许独立扩缩容,并可结合 Prefix Caching 进一步加速。

6.4 Speculative Decoding

VLLM 还支持 Speculative Decoding(推测解码):使用一个小模型(Draft Model)批量猜测多个后续 Token,再用大模型并行验证。接受率通常 70–90%,可将 effective token/s 提升 2–4 倍。

7. 性能对比与总结

各技术组合的实际性能收益

7.1 端到端性能对比

优化组合Throughput (tokens/s/GPU)显存占用 (70B)P50 Latency
Naive (PyTorch, batch=1) ~15 ~150 GB ~67 ms/token
+ Continuous Batching ~60 ~150 GB ~17 ms/token
+ PagedAttention (KV Cache) ~150 ~80 GB ~7 ms/token
+ W8A16 量化 ~300 ~45 GB ~3 ms/token
+ FP8 + TP4 ~600+ ~40 GB ~1.5 ms/token

*参考数据:LLaMA-2 70B @ H100 80GB SXM,throughput 为单卡,数据来自公开 benchmark 及生产环境测量。

7.2 技术选型决策树

GPU 显存够用? ✅ 是 → +PagedAttention ⚠️ 否 → +量化 + Continuous Batching W8A16 → W4A16 H100? → +FP8 + Prefix Cache

7.3 关键要点总结

🔄

Continuous Batching

以 iteration 为粒度调度,消除 GPU 空转,提升利用率 2–3x,是所有在线推理系统的基础。

📦

KV Cache

避免自回归步骤中重复计算,显存估算与 MQA/GQA 结合使用,是 Decode 阶段性能关键。

🔢

量化技术

W8A16 是生产首选,FP8 是 H100 的下一代方向,W4A16 适合显存极度受限场景。

🗂️

PagedAttention

分页管理 KV Cache,显存利用率从 30% 提升到 90%+,支持动态长度和 Prefix Caching。

🏗️

VLLM 架构

端到端优化,Scheduler + KV Cache Manager + Model Executor 三者协同是性能最大化的关键。

Speculative Decoding

通过小模型猜测+大模型验证,在接受率高(>70%)的场景可实现 2–4x 有效吞吐量提升。

7.4 未来方向

  • Disaggregated Prefill-Decode:更彻底的硬件解耦,结合 MoE 架构的 Expert Parallelism
  • KV Cache 分布式管理:跨节点 KV Cache 共享,解决超长上下文(100K+ tokens)的显存瓶颈
  • 硬件定制:Cerebras、Graphcore 等存算一体架构可能在未来改变 LLM 推理的 cost curve
  • W4A8 及更低精度:随着量化感知训练(QAT)和 GPTQ/AWQ 校准技术成熟,更激进量化将成为可能