系统优化
1. 长上下文与显存瓶颈
KV Cache 的线性增长
KV Cache 大小与序列长度线性增长:
显存需求示例
以 LLaMA-3-8B 为例(GQA, 8 KV heads, 32 layers, FP16):
| 序列长度 | KV Cache/请求 | 总显存需求 (Batch=32) |
|---|---|---|
| 4K | 0.5 GB | 16 GB |
| 8K | 1.0 GB | 32 GB |
| 32K | 4.0 GB | 128 GB |
| 128K | 16.0 GB | 512 GB |
| 1M | 128.0 GB | 不可行 |
核心矛盾:长上下文推理需要海量 KV Cache 存储,远超单 GPU 容量。
QUESTION 面试高频:大模型训练和推理时显存分别花在哪里?
训练阶段(以 7B 模型 BF16 为例):
组件 显存占用 说明 模型参数 14 GB 7B x 2 bytes 梯度 14 GB 与参数同大小 优化器状态 (Adam) 56 GB momentum + variance (FP32) 激活值 8-16 GB 取决于 batch size 和序列长度 总计 ~100 GB 单卡放不下 推理阶段(以 7B 模型 BF16 为例):
组件 显存占用 说明 模型参数 14 GB 7B x 2 bytes KV Cache 变化大 与序列长度和 batch 正比 激活值 2-4 GB 较小 框架开销 1-2 GB 固定 关键差异:训练显存约为推理的 4-6 倍。训练主要消耗在优化器状态和梯度,推理主要消耗在 KV Cache。
显存优化公式
模型参数显存:
Adam 优化器显存:
训练总显存估算:
(参数 FP16 + 梯度 FP16 + 优化器 FP32 + 激活值)
2. GPU 显存分配详解
推理场景的显存分配
GPU 显存 (80 GB A100)
├── 模型权重: 16 GB (8B FP16)
├── KV Cache: 60+ GB (长上下文)
├── 激活值: 2-4 GB
└── 框架开销: 1-2 GB
对于长上下文,KV Cache 成为绝对主导的内存消费者。
显存优化策略总览
| 优化方向 | 方法 | 节省效果 | 精度影响 |
|---|---|---|---|
| 模型量化 | FP16→INT4 | 模型体积减少 75% | 小(1-3%) |
| KV Cache 量化 | FP16→FP8 | KV Cache 体积减少 50% | 极小 |
| GQA | 减少 KV 头数 | KV Cache 减少 4-32× | 极小 |
| PagedAttention | 分页管理 | 利用率 20-40%→>95% | 无 |
| CPU Offloading | KV Cache 换出到 CPU | GPU 显存需求大幅降低 | 无(延迟略增) |
| 滑动窗口 | 固定 KV Cache 大小 | 与序列长度无关 | 有(丢失长距离信息) |
QUESTION 面试题:推理服务显存不足怎么办? 按优先级排序的优化策略:
- 量化:FP16→INT4/INT8,最快见效(模型体积减半至 1/4)
- PagedAttention:消除 KV Cache 碎片,利用率翻倍以上
- KV Cache 量化:FP16→FP8,KV Cache 减半
- 降低并发/序列长度:直接减少 KV Cache 需求
- CPU Offloading:不活跃的 KV Cache 换出到 CPU
- 多 GPU(TP):模型和 KV Cache 分布到多张卡
通常组合使用:量化 + PagedAttention + KV Cache 量化 可以在单卡上获得最佳性价比。
3. Attention 计算瓶颈
标准注意力的计算复杂度为 :
| 序列长度 | Attention FLOPs (相对) | 注意力矩阵大小 |
|---|---|---|
| 4K | 1x | 16M |
| 32K | 64x | 1B |
| 128K | 1024x | 16B |
| 1M | 65536x | 1T |
128K 序列的注意力计算量是 4K 的 1024 倍!
4. 长上下文优化技术
4.1 算法层面优化
Flash Attention(IO 感知的分块注意力)
- 避免存储完整 注意力矩阵
- 分块计算,减少 HBM 访问次数
- 使长序列训练和推理在计算层面可行
- 详见 推理加速
滑动窗口注意力(Sliding Window Attention)
只关注最近 个 Token + 少量"锚点" Token:
Token: [1] [2] [3] ... [N-W] [N-W+1] ... [N-1] [N]
窗口: |<-- 滑动窗口 -->|
锚点: ↑ ↑
Attention Sink Attention Sink
- 固定 KV Cache 大小: 而非
- StreamingLLM:保留初始几个 Token(Attention Sink)+ 滑动窗口
- 代表模型:Mistral(W=4096)、Gemma
StreamingLLM 详解
StreamingLLM 是一种使 LLM 拥有无限长生成能力的推理技术。
核心发现:Transformer 模型中存在 Attention Sink 现象 —— 大量注意力分数集中在序列开头的几个 Token 上,即使这些 Token 语义上不重要。
StreamingLLM 策略:
保留 Token: [Sink Tokens (前 4 个)] ... [最近的 W 个 Token]
├─ 固定保留 ──┤ ├─ 滑动窗口 ──┤
- 保留 Attention Sink:始终保留序列开头的几个 Token(通常 4 个)
- 滑动窗口:只缓存最近 个 Token 的 KV Cache
- 滚动更新:新生成的 Token 追加到窗口,超出窗口的 Token 被淘汰
优势:
- KV Cache 固定为 ,不随序列长度增长
- 无需微调或修改模型
- 可以无限长度生成(已验证 400 万+ Token)
局限:
- 丢失长距离依赖信息(超出窗口的 Token 信息丢失)
- 对需要全文理解的场景不适用(如文档摘要)
QUESTION 面试题:什么是 Attention Sink?StreamingLLM 如何利用它? Attention Sink 是指 Transformer 中大量注意力集中在序列开头几个 Token 上的现象。研究发现,即使这些 Token 是无意义的填充 Token,模型也会将大量注意力分配给它们。
原因分析:Softmax 需要所有注意力权重之和为 1,当模型不确定关注哪些 Token 时,倾向于将"多余的"注意力分配给开头的 Token 作为"Sink"。
StreamingLLM 利用这个发现:
- 始终保留开头的 Sink Token(通常 4 个),防止注意力崩溃
- 配合滑动窗口,只缓存最近 个 Token
- 实现 固定大小的 KV Cache,支持无限长度生成
去掉 Sink Token 会导致模型输出质量急剧下降(注意力机制失效)。
稀疏注意力(Sparse Attention)
只计算部分 Token 对之间的注意力:
- 局部注意力:只关注邻近 Token
- 全局 Token:少数 Token 与所有 Token 做注意力
- 随机注意力:随机选择部分远距离 Token
- 混合模式:局部 + 全局 + 随机
GQA / MQA
减少 KV 头数以降低 KV Cache 大小:
| 方法 | KV 头数 | KV Cache 压缩比 |
|---|---|---|
| MHA | 32 | 1x |
| GQA-8 | 8 | 4x |
| GQA-4 | 4 | 8x |
| MQA | 1 | 32x |
4.2 KV Cache 管理优化
KV Cache 量化
| 精度 | 大小 | 精度影响 | 适用场景 |
|---|---|---|---|
| FP16 | 2 bytes | 基准 | 通用 |
| FP8 | 1 byte | 极小 | 推荐 |
| INT4 | 0.5 bytes | 可接受 | 极致压缩 |
| KIVI (2-bit) | 0.25 bytes | 有损失 | 研究 |
KV Cache 淘汰(Token Eviction)
- H2O (Heavy-Hitter Oracle):保留注意力分数累积最高的 Token
- Scissorhands:保留"关键"Token,移除冗余 Token
- CacheGen:基于信息论的压缩
# H2O 伪代码
def evict_tokens(kv_cache, attention_scores, budget):
# 计算每个 Token 的累积注意力分数
scores = attention_scores.sum(dim=0)
# 保留分数最高的 budget 个 Token
top_k = scores.topk(budget)
return kv_cache[:, top_k.indices]
跨层 KV 共享
某些架构(如 MiniCPM、Adaptive-Layer KV)共享相邻层的 KV Cache:
- 减少总 KV 存储量
- 适用于层间 KV 差异小的模型
4.3 分布式推理优化
Ring Attention
将序列分块分布到多个 GPU,以环形拓扑传递 KV Block:
GPU 0: 处理 Block 0 → 传递 KV Block 0 给 GPU 1
GPU 1: 处理 Block 1 → 传递 KV Block 1 给 GPU 2
...
GPU N: 处理 Block N → 传递 KV Block N 给 GPU 0
每轮传递一个 KV Block,N 轮后所有 GPU 都有完整的 KV 序列
计算与通信重叠(overlap)
- 支持接近无限长的上下文(100M+ Token)
- 计算与通信完全重叠
- 关键:Block 大小需足够大以隐藏通信延迟
4.4 位置编码扩展
RoPE 扩展方法
训练时使用较短上下文,推理时扩展到更长上下文。
| 方法 | 原理 | 是否需要微调 | 效果 |
|---|---|---|---|
| 直接外推 | 不做任何修改 | 否 | 差(长序列性能急剧下降) |
| Position Interpolation | 缩放位置索引 | 否/少量 | 中等 |
| NTK-aware Scaling | 调整 RoPE 基频 | 否 | 良好 |
| YaRN | 混合缩放策略 | 否 | 优秀 |
| ALiBi | 线性注意力偏置 | 否 | 良好 |
YaRN (Yet another RoPE extensioN method)
结合三种缩放策略:
- 温度缩放:调整注意力温度
- NTK-aware 缩放:修改 RoPE 基频
- 混合缩放:对近程和远程 Token 使用不同策略
近距离 Token → 原始位置编码(保持精度)
中距离 Token → 线性插值
远距离 Token → NTK-aware 缩放(保持泛化)
- 零训练:不需要额外微调
- 低开销:推理时即可生效
- 广泛应用:LLaMA-3、Qwen-2.5 等均使用类似方法
4.5 系统层面优化
Chunked Prefill
将长 Prompt 分块处理,避免单个长 Prefill 阻塞所有请求:
标准 Prefill:
[████████████████████████████] 200ms (阻塞)
Chunked Prefill:
[████][████][████][████] 每块 50ms
↑ ↑ ↑ ↑
可以穿插其他请求的 Decode
好处:
- 长请求不会阻塞短请求
- Prefill 和 Decode 可以交替执行
- 降低 P99 TTFT
分页 KV Cache + 前缀缓存
- PagedAttention 管理不连续的 KV Block(详见 vLLM)
- 多请求共享 System Prompt 的 KV Cache
CPU Offloading
将不活跃的 KV Cache 暂存到 CPU 内存:
GPU: 当前活跃请求的 KV Cache
CPU: 不活跃请求的 KV Cache
需要时从 CPU 加载到 GPU
5. 长上下文推理架构
典型部署方案
场景: 128K 上下文, 8B 模型
方案 1: 单 GPU (80GB A100) + FP8 KV Cache
KV Cache: ~8 GB/请求 → 支持 ~6 个并发
方案 2: 2 GPU (TP=2) + FP16 KV Cache
KV Cache: ~16 GB/请求 → 支持 ~8 个并发
方案 3: 单 GPU + 滑动窗口 (W=8K)
KV Cache: ~1 GB/请求 → 支持 ~60 个并发
但丢失长距离依赖信息
方案 4: 4 GPU + Ring Attention
KV Cache 分布在 4 GPU → 支持 1M+ 上下文
方案选择决策
需要长上下文推理?
│
├─ 否(短文本)──→ 标准部署 + PagedAttention
│
├─ 是 ──────────┐
│ ├─ 可接受丢失长距离信息 ──→ 滑动窗口 / StreamingLLM
│ ├─ 需要完整上下文 ──┐
│ │ ├─ 单卡够 ──→ FP8 KV Cache + Chunked Prefill
│ │ └─ 不够 ──→ TP + Ring Attention
│ └─ 极致吞吐 ──→ 量化 + Continuous Batching + Prefix Caching
QUESTION 面试题:如何为一个 128K 长上下文的在线服务设计部署方案? 需要权衡并发量、延迟和成本:
- 单卡方案(80GB A100):FP8 KV Cache,8B 模型每请求 ~8 GB,支持 ~6 并发。成本最低但并发有限
- 双卡方案(TP=2):FP16 KV Cache,16 GB/请求,8 并发。推荐方案
- 多卡 + Ring Attention:4+ 卡,支持 1M+ 上下文。成本最高
- 量化 + 滑动窗口:如果可接受丢失长距离信息,可用滑动窗口大幅提升并发
关键技术组合:GQA + PagedAttention + FP8 KV Cache + Chunked Prefill + Continuous Batching
6. 系统优化技术全景
推理加速技术分类
| 层级 | 技术 | 效果 | 适用阶段 |
|---|---|---|---|
| 算法层 | FlashAttention | 2-4× 加速 | Prefill + Decode |
| 算法层 | 投机解码 | 1.5-3× 加速 | Decode |
| 算法层 | GQA/MQA | KV Cache 减少 4-32× | Decode |
| 算法层 | 滑动窗口 | 固定 KV Cache | Decode(长序列) |
| 模型层 | 量化 (INT4/INT8) | 模型体积减 75-50% | 全阶段 |
| 模型层 | KV Cache 量化 | KV 体积减 50-75% | Decode |
| 系统层 | Continuous Batching | 吞吐 2-4× | 在线服务 |
| 系统层 | PagedAttention | KV 利用率 >95% | 在线服务 |
| 系统层 | Chunked Prefill | 减少 TTFT 阻塞 | 长上下文 |
| 系统层 | Prefix Caching | 避免重复计算 | System Prompt |
| 硬件层 | Tensor Parallelism | 线性加速 | 大模型 |
| 硬件层 | CPU Offloading | 扩展显存 | 显存不足 |
7. 2025 年趋势
- 原生长上下文模型:Gemini 2.0 (1-2M Token)、Claude (200K)、GPT-4 (128K)
- 混合注意力架构:Mamba + Attention 混合模型(Jamba 等)
- KV Cache 压缩成为标配:FP8 KV Cache 在主流推理引擎中默认支持
- 分块 Prefill 与 Chunked Attention:长 Prompt 不再阻塞短请求
- Ring Attention 的工程化:从研究走向生产部署
- Context Distillation:将长上下文压缩为短表示,用于后续推理
- 推理框架大一统:vLLM、SGLang、TensorRT-LLM 功能趋同,差异化在性能优化深度