Compute-bound vs Memory-bound:推理的两大瓶颈
1. 核心概念:两种瓶颈
GPU 执行任何计算都涉及两件事:
- 计算:ALU 做矩阵乘法等运算(受 TFLOPS 限制)
- 访存:从显存读取数据到计算单元(受 HBM 带宽限制)
┌──────────────┐ ┌──────────────┐
│ HBM 显存 │ ──── 带宽 ────→ │ 计算单元 │
│ (存权重/KV) │ (Memory BW) │ (做矩阵乘) │
└──────────────┘ └──────────────┘
如果计算单元等数据:Memory-bound(带宽瓶颈)
如果数据等计算完成:Compute-bound(算力瓶颈)
关键指标:算术强度 (Arithmetic Intensity)
算术强度 = FLOPs / Bytes accessed
= 做了多少计算 / 搬了多少数据
- 算术强度高 → Compute-bound(计算密集,GPU 算力是瓶颈)
- 算术强度低 → Memory-bound(访存密集,显存带宽是瓶颈)
2. Prefill 阶段:Compute-bound
2.1 为什么是算力瓶颈?
Prefill 一次性处理整个 prompt(可能几百到几千个 token),核心操作是大矩阵乘法:
输入: X [batch, seq_len, hidden_dim] 如 [1, 2048, 4096]
权重: W [hidden_dim, hidden_dim] 如 [4096, 4096]
输出: Y = X · W [1, 2048, 4096]
FLOPs ≈ 2 × batch × seq_len × hidden² = 2 × 1 × 2048 × 4096² ≈ 68.7 GFLOPs
Bytes = 权重读取 = 4096 × 4096 × 2 = 33.5 MB
算术强度 = 68.7G / 33.5M ≈ 2048 ← 非常高!
seq_len 越大,算术强度越高,越是 compute-bound。GPU 的 TFLOPS 决定了 prefill 速度。
2.2 Prefill 的性能特征
Prefill 性能 ≈ 模型 FLOPs / GPU TFLOPS
例:Llama-3-8B prefill 2048 tokens
总 FLOPs ≈ 2 × 8B × 2048 ≈ 32.8 TFLOPs
A100 (312 TFLOPS FP16) → 理论时间 ≈ 32.8/312 ≈ 105ms
H100 (990 TFLOPS FP16) → 理论时间 ≈ 32.8/990 ≈ 33ms
关键洞察:
- 提高 batch size 对 prefill 友好(矩阵更大,GPU 利用率更高)
- 更强的 GPU(更高 TFLOPS)直接加速 prefill
- FlashAttention 通过减少 HBM 访问来优化 prefill 中的 attention 计算
3. Decode 阶段:Memory-bound
3.1 为什么是带宽瓶颈?
Decode 每次只处理 1 个 token,核心操作变成了矩阵-向量乘法:
输入: x [batch, 1, hidden_dim] 如 [1, 1, 4096]
权重: W [hidden_dim, hidden_dim] 如 [4096, 4096] ← 权重没变!
输出: y = x · W [1, 1, 4096]
FLOPs ≈ 2 × 1 × 1 × 4096² ≈ 33.5 MFLOPs
Bytes = 权重读取 = 4096 × 4096 × 2 = 33.5 MB
算术强度 = 33.5M / 33.5M ≈ 1 ← 极低!
每读 1 byte 数据只做 1 次运算,GPU 的计算单元大部分时间在等数据。
3.2 Decode 的性能特征
Decode 每 token 延迟 ≈ 模型参数量 × bytes_per_param / GPU 带宽
例:Llama-3-8B decode (FP16)
数据量 = 8B × 2 bytes = 16 GB(每步都要读一遍所有权重)
A100 带宽 = 2 TB/s → 理论时间 ≈ 16/2000 ≈ 8ms/token → ~125 tokens/s
H100 带宽 = 3.35 TB/s → 理论时间 ≈ 16/3350 ≈ 4.8ms/token → ~208 tokens/s
关键洞察:
- 显存带宽比算力更影响生成速度
- 单请求 decode 时 GPU 计算利用率极低(可能 <5%)
- 增大 batch 可以提高利用率(同一份权重服务多个请求)
- 量化(FP16→INT8→INT4)直接减少要读的数据量,加速 decode
3.3 为什么 Decode 怎么优化都快不太多?
单请求 decode 的理论下限 = 模型大小 / 显存带宽
这是物理限制:
- 每生成 1 个 token,必须读一遍所有模型权重
- 读取速度受限于 HBM 带宽
- 除非减小模型(量化)或增加带宽(更好的硬件),否则无法突破
A100: 8B FP16 → 最快 ~8ms/token
H100: 8B FP16 → 最快 ~4.8ms/token
H100: 8B INT4 → 最快 ~1.2ms/token ← 量化 4 倍,速度提 4 倍
4. Roofline 模型:可视化性能瓶颈
Roofline 模型是分析 GPU 程序性能的经典工具:
性能 (FLOPS)
│
│ ╱ ← 带宽上限斜线 (Memory-bound 区域)
│ ╱
│ ╱
│ ╱─────────────── ← 算力上限 (Compute-bound 区域)
│ ╱
│ ╱
│ ╱
│ ╱
│ ╱
│╱
└──────────────────────── 算术强度 (FLOPs/Byte)
↑
拐点 = Peak FLOPS / Peak BW
A100 拐点 = 312 TFLOPS / 2 TB/s = 156 FLOPs/Byte
算术强度 < 156 → Memory-bound(decode 阶段,AI ≈ 1)
算术强度 > 156 → Compute-bound(prefill 阶段,AI ≈ 2048)
5. 实际影响:为什么这些知识很重要?
5.1 硬件选型
| 场景 | 瓶颈 | 选卡策略 |
|---|---|---|
| 长 prompt prefill | Compute-bound | 选高 TFLOPS(H100 > A100) |
| 实时对话 decode | Memory-bound | 选高带宽(HBM3 > HBM2e) |
| 高并发服务 | 两者都有 | 需要平衡 TFLOPS 和带宽 |
5.2 优化策略映射
| 优化技术 | 主要加速阶段 | 原理 |
|---|---|---|
| FlashAttention | Prefill | 减少 HBM 访问,在 SRAM 中完成 attention |
| 量化 (INT8/INT4) | Decode 为主 | 减少权重数据量,降低带宽需求 |
| 增大 batch | Decode 为主 | 同一份权重服务多请求,提高算术强度 |
| Tensor Parallelism | 两者 | 多卡分摊计算和带宽 |
| Speculative Decoding | Decode | 用小模型猜测,大模型批量验证 |
| KV Cache 量化 | Decode | 减少 KV 读取的数据量 |
5.3 Batch Size 对两阶段的不同影响
Prefill (seq_len=2048):
batch=1: 算术强度 ≈ 2048 → Compute-bound ✓
batch=32: 算术强度 ≈ 2048 → 还是 Compute-bound(seq_len 已经够大)
→ batch 增大主要增加总吞吐量
Decode (seq_len=1):
batch=1: 算术强度 ≈ 1 → Memory-bound ✗
batch=32: 算术强度 ≈ 32 → 还是 Memory-bound,但好多了
batch=256:算术强度 ≈ 256 → 接近拐点,GPU 利用率大幅提升
→ batch 增大是 decode 阶段最有效的优化手段之一
这就是为什么推理服务(vLLM/TGI)都在拼命做 batching。
6. 关键要点总结
┌──────────────────────────────────────────────────────────┐
│ Compute vs Memory Bound 核心认知 │
├──────────────────────────────────────────────────────────┤
│ 1. Prefill = 大矩阵乘 = Compute-bound = 看 TFLOPS │
│ 2. Decode = 矩阵向量乘 = Memory-bound = 看 HBM 带宽 │
│ 3. 算术强度 = FLOPs/Bytes,决定瓶颈在哪 │
│ 4. Decode 的理论下限 = 模型大小 / 显存带宽 │
│ 5. 增大 batch 是提升 decode GPU 利用率的关键 │
│ 6. 量化通过减少数据量直接加速 memory-bound 的 decode │
└──────────────────────────────────────────────────────────┘
7. 延伸阅读
- LLM Inference Optimization — Prefill vs Decode — 两阶段优化的工程视角
- Full-Stack Acceleration for LLMs — 全栈加速技术概览
- SRAM-Frequency Tradeoffs and the Memory-Bandwidth Ceiling (arxiv) — 学术论文,深入分析 SRAM/频率对两阶段的影响
- A Systematic Characterization of LLM Inference on GPUs — GPU 推理的系统性分析
修改历史1 次提交
- docs(ai-systems): add comprehensive LLM inference documentationxiaocheng··
7c98505