先记住一句话
Arithmetic intensity = FLOPs / bytes moved;它决定 kernel 更可能撞到计算屋顶还是带宽斜坡,fusion/tiling 的价值主要是减少慢速层流量。
1. Memory hierarchy
| 层级 | scope | 特点 |
|---|---|---|
| Registers | thread | 最快、容量最小;过多降低 occupancy/spill |
| Shared memory / L1 | block / SM | on-chip、software-managed reuse;受 bank/layout 影响 |
| L2 | device | SM 间共享 cache,缓解 HBM traffic |
| HBM/global memory | device | 容量与带宽大,latency 高 |
| Host memory | CPU | 经 PCIe/NVLink-C2C 等互连,通常更远 |
2. Roofline 公式
attainable FLOP/s ≤ min(peak_compute, memory_bandwidth × arithmetic_intensity)图上 x 轴是 FLOP/byte,y 轴是 FLOP/s。低 intensity 落在 bandwidth slope,是 memory-bound;高 intensity 达到水平 compute roof,是 compute-bound。实际还有 L1/L2/shared 等 hierarchical rooflines。
3. 一个 vector add 为什么 memory-bound
C=A+B 每元素约 1 add,却需读 A/B、写 C。即便 float32 只按 12 bytes 估算,intensity 约 1/12 FLOP/byte,远低于现代 GPU compute-to-bandwidth 比。换 Tensor Core 没意义,减少 passes/fuse 才有用。
4. GEMM 为什么能 compute-bound
naive GEMM 每个 output 做 K 次 multiply-add。若 A/B tiles 放进 shared/register 后在多个 outputs 间复用,同一 byte 支撑许多 FLOPs,intensity 随 tile 增长。若每个 thread 从 HBM 重读同样 A/B,理论 O(MNK) 算法仍可能 memory inefficient。
5. Bytes moved 应在哪一层数
源码 load 次数不等于 DRAM transactions:cache hit、write allocation、alignment、ECC 与 replay 都改变流量。先用 algorithmic lower bound 建模,再用 profiler 的 DRAM/L2 sectors 和 throughput 验证。不要用 tensor size 简单代替真实 traffic。
6. Fusion 的 Roofline 解释
unfused: GEMM → write HBM → bias → write HBM → activation → write HBM
fused: GEMM accumulator → bias + activation in registers → one final writefusion 减少 intermediate traffic 和 launches;但融合太多会增加 registers/shared memory、降低 occupancy,或阻止调用高度优化的 library kernel。
7. Data layout 也是算法
row/column-major、NCHW/NHWC、contiguous/strided、packing 和 alignment 决定 transaction、vector load 与 Tensor Core path。layout conversion 本身有成本;全图编译器可一起选 layouts,单算子 microbenchmark 可能隐藏 reformat。
8. Cache 不是自动解决一切
working set 超 cache、访问无复用、多个 kernels 竞争或 stride 映射差时 cache hit 低。shared memory 明确控制 tile reuse,但要付 cooperative load、sync、容量与 bank-conflict 成本。
9. Roofline 的边界
它给上限与 bottleneck class,不预测所有 latency:小 kernel 可能 launch-bound,dependency-bound;integer/special-function/atomics 的“peak”不同;irregular sparse workload 受 load imbalance。要结合 timeline 与 instruction/memory metrics。
10. 四个 Roofline 手算
例 1:vector add intensity
C=A+B 每 element 读 A/B 8 bytes、写 C 4 bytes,共 12 bytes,做 1 FLOP,intensity=1/12=0.083 FLOP/byte,通常强 memory-bound。
例 2:带宽屋顶
HBM bandwidth=1.5 TB/s,kernel intensity=2 FLOP/byte,bandwidth roof=1.5×2=3 TFLOP/s。即使 GPU compute peak=60 TFLOP/s,也最多约 3。
例 3:ridge point
Compute peak=60 TFLOP/s、bandwidth=1.5 TB/s,ridge intensity=60/1.5=40 FLOP/byte。低于 40 更可能在带宽斜坡,高于 40 才可能撞 compute roof。
例 4:fusion 减 HBM traffic
两个 kernels 中间产生 100 MB tensor:未 fusion 至少写 100 MB 再读 100 MB;fusion 后保存在 registers/shared 可省约 200 MB。1 TB/s 下理论节省 0.2 ms,实际还含 launch/cache 效应。
memory-bound 不等于 GPU memory 已满。它表示相对当前 work/traffic ratio,性能由供数速率限制;利用率低还可能来自不合并访问、latency、太小 workload 或 serialization。
自测
1. fusion 为什么常加速 elementwise chain?
把 intermediates 留在 registers/on-chip,减少 HBM read/write 和 launch 次数。
2. 提高 FLOPs 一定变慢吗?
不一定;若多做少量计算能显著减少 memory traffic/recompute,memory-bound kernel 反而更快。
3. Roofline 需要哪两个硬件上限?
目标 dtype/instruction 的 peak compute rate,以及对应 memory level 的 peak/可持续 bandwidth。
官方资料
Nsight Compute Profiling Guide给出 arithmetic intensity 与 Roofline;CUDA Best Practices覆盖各 memory spaces 与 bandwidth 优化。