Roofline 模型通过操作强度将算法特征与硬件能力关联,精准定位性能瓶颈(内存带宽受限/算力受限)。
核心概念
操作强度
$$OI = \frac{\text{浮点操作数}(FLOPs)}{\text{片外内存访问量}(Bytes)}$$
Roofline 公式
$$P_{max} = \min(P_{peak}, OI \times B_{max})$$
| 符号 | 定义 |
|---|
| $P_{max}$ | 程序最大性能 |
| $P_{peak}$ | 硬件峰值算力 |
| $B_{max}$ | 峰值内存带宽 |
| $OI_{ridge}$ | 临界操作强度 = $P_{peak}/B_{max}$ |
瓶颈判定
| 条件 | 瓶颈类型 |
|---|
| $OI < OI_{ridge}$ | 内存带宽受限 |
| $OI > OI_{ridge}$ | 算力受限 |
主流 GPU 参数
| GPU | FP16 算力 (TFLOPS) | 带宽 (GB/s) | $OI_{ridge}$ |
|---|
| H100 SXM | 989 | 3350 | 295 |
| A100 SXM | 312 | 2039 | 153 |
| V100 SXM | 125 | 900 | 138 |
常见算子操作强度
| 算子 | 操作强度 | 瓶颈类型 |
|---|
| 大矩阵乘法 | >50 | 算力受限 |
| 小矩阵乘法 | <10 | 带宽受限 |
| Element-wise | ≈0.3 | 严重带宽受限 |
| LayerNorm | <10 | 带宽受限 |
LLM 推理分析
| 阶段 | 操作强度 | 瓶颈 |
|---|
| Prefill | $2 \times seq_len$ | 算力受限(长序列) |
| Decode | 2 | 带宽受限 |
优化策略
| 瓶颈类型 | 优化方向 |
|---|
| 带宽受限 | 分块计算、算子融合、量化 |
| 算力受限 | 剪枝、Tensor Core、向量化 |
绘图代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| import matplotlib.pyplot as plt
import numpy as np
devices = [
{"name": "H100", "fp16_tflops": 989, "bw_gbps": 3350},
{"name": "A100", "fp16_tflops": 312, "bw_gbps": 2039},
]
plt.figure(figsize=(10, 6))
x = np.logspace(-1, 3, 100)
for dev in devices:
y_bw = (dev["bw_gbps"] * 1e9) * x / 1e12
y_flops = np.full_like(x, dev["fp16_tflops"])
y_roof = np.minimum(y_bw, y_flops)
plt.loglog(x, y_roof, label=dev["name"], linewidth=2)
plt.xlabel("OI (FLOPs/Byte)")
plt.ylabel("Performance (TFLOPS)")
plt.legend()
plt.grid(True, which="both", ls="--")
plt.show()
|
中文教程:https://lqhl.github.io/scaling-book/roofline/
Comments