推理优化的核心矛盾
大模型推理面临一个核心矛盾:用户需要低延迟和高吞吐,但自回归生成天然是串行的。每生成一个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-4bit | 1-3% | 2-3x | 消费级GPU |
| AWQ-4bit | 0.5-2% | 2-3x | 活跃权重保护 |
| FP8 (H100) | <0.5% | 2x | H100部署 |
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倍
部署架构建议
对于生产环境的大模型推理服务,推荐架构:
- 前端:Nginx/Traefik做负载均衡
- 推理引擎:vLLM/TensorRT-LLM/SGLang
- 模型存储:本地SSD + 模型缓存
- 监控:Prometheus + Grafana监控GPU利用率、延迟分布
关键配置建议:
max_num_seqs:根据GPU显存设置,通常64-128gpu_memory_utilization:0.90-0.95- 启用prefix caching缓存相同system prompt
结语
推理优化是一个系统工程,从算法层面(注意力优化、投机解码)到系统层面(PagedAttention、连续批处理)再到硬件层面(量化、FP8),需要全栈协同。随着Blackwell架构GPU的普及,FP8和Transformer Engine将进一步降低推理成本。