推理优化的核心矛盾

大模型推理面临一个核心矛盾:用户需要低延迟和高吞吐,但自回归生成天然是串行的。每生成一个token都需要完整的前向传播,而KV Cache的显存占用随序列长度线性增长。本文系统梳理当前主流的推理优化技术。

KV Cache优化

KV Cache的工作原理

在自回归生成中,前面token的Key和Value可以缓存复用,避免重复计算。但KV Cache的显存占用惊人:

$$\text{KV Cache Size} = 2 \times n_{layers} \times n_{heads} \times d_{head} \times seq_len \times batch_size \times \text{dtype_size}$$

以Llama-3-70B为例,FP16精度下,单条2048长度的请求KV Cache就需要约5GB显存。

PagedAttention

vLLM的PagedAttention借鉴操作系统的虚拟内存管理,将KV Cache分成固定大小的block(如16个token),按需分配:

# vLLM的核心创新:非连续KV Cache存储
class PagedAttention:
    def __init__(self, block_size=16):
        self.block_size = block_size
        self.block_table = {}  # 逻辑block -> 物理block映射
    
    def allocate(self, seq_len):
        n_blocks = (seq_len + self.block_size - 1) // self.block_size
        return [self._alloc_block() for _ in range(n_blocks)]

PagedAttention将显存利用率从约60%提升到96%以上,显著提高并发处理能力。

KV Cache量化

将KV Cache从FP16量化到INT8可以减半显存占用,而精度损失可控:

# vLLM中启用KV Cache量化
from vllm import LLM, SamplingParams

llm = LLM(
    model="meta-llama/Meta-Llama-3-70B",
    quantization="fp8",           # 模型权重量化
    kv_cache_dtype="fp8",         # KV Cache量化
    max_model_len=8192,
)

注意力机制优化

Flash Attention 2/3

Flash Attention通过分块计算和减少HBM读写,将注意力计算复杂度从 $O(n^2)$ 内存降到 $O(n)$ 内存:

  • Flash Attention 2:优化了GPU线程分配,提升约2倍速度
  • Flash Attention 3:利用H100的异步拷贝和FP8支持,比FA2再快1.5-2倍

Multi-Query Attention与GQA

标准Multi-Head Attention中,每个头都有独立的K/V矩阵。GQA(Grouped-Query Attention)让多个头共享K/V,大幅减少KV Cache大小:

  • MQA:所有头共享1组K/V,KV Cache减少 $n_{heads}$ 倍
  • GQA:分成 $n_{groups}$ 组,平衡质量和效率
  • Llama-3-70B使用GQA,8组K/V服务64个头

模型量化

量化方法对比

方法精度损失推理速度适用场景
FP16基准基准生产基线
INT8 (W8A8)<1%1.5-2x高精度需求
GPTQ-4bit1-3%2-3x消费级GPU
AWQ-4bit0.5-2%2-3x活跃权重保护
FP8 (H100)<0.5%2xH100部署

AWQ(Activation-aware Weight Quantization)通过分析激活值分布保护重要权重通道,在4bit量化下几乎无损:

from autoawq import AutoAWQForCausalLM
model = AutoAWQForCausalLM.from_quantized(
    "TheBloke/Llama-3-70B-AWQ",
    fuse_layers=True,    # 算子融合
    device_map="auto"
)

投机解码

投机解码利用小模型快速生成草稿,大模型并行验证。如果草稿正确,可以一次生成多个token:

def speculative_decode(prompt, draft_model, target_model, max_tokens=4):
    # 1. 小模型快速生成草稿
    draft_tokens = draft_model.generate(prompt, max_new_tokens=max_tokens)
    
    # 2. 大模型并行验证
    target_logits = target_model.forward(prompt + draft_tokens)
    accepted = 0
    for i, token in enumerate(draft_tokens):
        target_token = target_logits[i].argmax()
        if token == target_token:
            accepted += 1
        else:
            break  # 首个不匹配处终止
    
    # 3. 返回接受的token + 大模型修正的token
    return draft_tokens[:accepted] + [target_logits[accepted].argmax()]

实测中,使用Llama-3-8B作为Llama-3-70B的草稿模型,端到端速度提升约2倍。

连续批处理

传统批处理需要等待所有请求完成才能释放资源。连续批处理(Continuous Batching)在每步迭代级别动态管理批次,新请求可以随时加入:

vLLM默认启用连续批处理,配合PagedAttention实现高吞吐:

  • 单张A100处理Llama-3-8B可达5000+ tokens/s吞吐
  • 相比静态批处理提升3-5倍

部署架构建议

对于生产环境的大模型推理服务,推荐架构:

  1. 前端:Nginx/Traefik做负载均衡
  2. 推理引擎:vLLM/TensorRT-LLM/SGLang
  3. 模型存储:本地SSD + 模型缓存
  4. 监控:Prometheus + Grafana监控GPU利用率、延迟分布

关键配置建议:

  • max_num_seqs:根据GPU显存设置,通常64-128
  • gpu_memory_utilization:0.90-0.95
  • 启用prefix caching缓存相同system prompt

结语

推理优化是一个系统工程,从算法层面(注意力优化、投机解码)到系统层面(PagedAttention、连续批处理)再到硬件层面(量化、FP8),需要全栈协同。随着Blackwell架构GPU的普及,FP8和Transformer Engine将进一步降低推理成本。