来源:http://cuckoohash.org/posts/roofline/
¶概念
我们知道,一个计算任务 (小到矩阵乘法、大到神经网络的训练) 的性能表现,取决于任务本身的特性以及计算平台的指标。
计算平台的主要指标有两个:算力和带宽。算力即每秒峰值浮点运算次数 (Peak Flops/sec);带宽即每秒峰值内存数据存取量 (Peak Memory Bandwidth),单位是 Byte/sec。
计算任务相应的主要指标则是运算量(单位是 Flops) 和访存量(单位是 Bytes)。
¶Roofline Model
给定一个计算任务和平台,我们最关心的指标是,任务在该平台上的每秒浮点运算次数 (Attainable Flops/sec)。如果不存在内存带宽的限制,那么任务的理想性能显然是计算平台的算力。 但是在很多情况下,内存访问会成为瓶颈,这时计算任务的性能就达不到平台的峰值算力了。
为了考虑访存对性能的影响,作者首先定义了 Operational Intensity (运算强度) 为运算量和访存量的比值 (Flops/byte),即单位内存访问用于多少次浮点计算。一个任务的运算强度越大,内存使用效率越高。
Roofline Model 提出了一个非常简单的模型来计算任务的每秒浮点运算次数:
1 | Attainable Flops/sec = Min(Peak Flops/sec, Peak Memory Bandwidth * Operational Intensity) |
如果以运算强度为横轴、每秒浮点运算次数为纵轴画图,我们可以得到一条与计算平台相关的折线,即所谓的 Roofline。算力决定屋顶的高度,带宽决定屋檐的斜率。所有在这个平台上运行的计算任务能够达到的性能都处于屋顶的下方。
¶分析
由图 1(a) 可见,「屋顶」把瓶颈划分为两个区域:
- Memory-bound: 当任务的运算强度小于平台的运算强度上限 (算力与带宽的比值) 时,任务的性能受限于内存带宽。此时平台带宽越大,或者任务的运算强度越大,任务性能越好。
- Compute-bound: 当任务的运算强度大于平台的上限时,性能受限于算力。此时平台算力越高,任务性能越好。
作者提出,Roofline Model 可以对如何优化当前计算任务的性能提供参考。我们可以把可能的优化手段分成两类:
- 提高算力
- 指令集并行:循环展开、SIMD 指令
- 平衡不同类型浮点运算的数量,使得编译器可以最大程度利用乘积累加运算指令 (Fused multiply-add)
- 提高带宽
- 在循环中使用单位步长访问数组,以利用硬件 Prefetching 的特性
- 在 NUMA 系统里利用内存的 Affinity
- 使用软件 Prefetching
在同一个平台上,计算任务的运算强度不同,其性能瓶颈的类型也不同。对于 Memory-bound 的任务,优化内存带宽更加有效;而对于 Compute-bound 的任务,则应该优化算力。
¶总结
这篇文章介绍了 Roofline Model 的概念,以及如何利用 Roofline Model 来估算一个计算任务在特定平台上的性能上限。但是由于缓存以及其他因素的影响,系统的实际性能往往很难达到 Roofline 的上限。