compute bound or memory bound

之前对这两个名词有误解,没有多么深刻的认知

Compute bound: computationally intensive, the time involved in the computation is much longer than I/O operation, e.g. linear and conv. Memory bound: the time involved in I/O operation is bigger.
直到今天问了mingfei大神~~

首先关于这个IO的概念是不对的,

IO指的是从硬盘drive到内存memoryIO的带宽是有PCI-e决定的,PCIe 4.0的带宽是上行下行各8GB/s
Memory BW是从内存到cache,这个就是你内存条带宽 * port数量,一般CPU是100+GB/s; GPU有HBM(high bandwidth memory) v100好像是一千多
一般L1的带宽应该是两千多,多以利用好你的L1而不要让code等在Memory的BW上。。。

比如你的CPU 每个cycle可以进行1次FMA的运算,但是每个cycle只能load 1个float (4个Byte)
那么。。。

1
a = b + c

这个算式是被什么bound呢,这里只有一个add能不能在1个cycle内完成呢?
答案是否定的,因为要读b和c(8 byte), 写一次a(写实际是一次读一次写,就是8byte)。。。

这样你就应该很容易理解

我们的CPU peak ALU吞吐量在9Tflops/sec左右,mem带算宽180GB/s,这个ratio就是:

1
Ratio = 9 * 1024 Gflops / 180 Gbytes =  50

那么一个byte对应50次fma,高于这个ratio的是compute bound,低于这个ratio的是mem BW bound。这个叫static analysis实际情况要复杂很多。

做性能预测的时候大概就是这个算法,比如一个gemm,不一定是compute bound,MNK如果又一边很小,就是mem BW bound…
一般硬件在设计的时候都会让o(n3)的运算compute bound。我们可以对一个kernel进行详细的分析:

  • 多少次计算
  • 多少load
  • 有没有重用(cache影响,有的话是L1/L2/LLC那一个位置)

有了上述条件你就可以算出理论性能上限。。。

当然大多数情况下我们根本达不到理论上限, 为什么呢??

一般写的比较好的kernel在vtune里面查CPI(cycles per instruction)应该在0.5以下,如果出现十几这种情况一般是: 有频繁函数调用,访存不连续,还有就是慢速指令(比如整数的除法或者取模,非常慢)

再举个很简单的例子比如fuse 一个kernel:

1
2
a = a * alpha
a = a + b

假设a和b都是n长度的tensor.

那么地球人知道要fuse起来比较快,为什么呢?这里我们不考虑fma的情况,就假定这是两次运算

  • 单独计算的时候要读a两次,读b一次,写a两次
  • Fuse起来a读写各一次,b读一次

如果有复用的情况还要考虑cache(这就是大师说的对于L1的优化,L1速度比reg慢一下但差不多)
这时候就要做Blocking,如果做得好还可以规避掉leading dimension的问题。。。这个问题很常见,因为AI里面很多都是256, 512, 1024这种数,很可能下次循环就把上次循环cache的一条数据给flush了。。。

详情请关注大佬即将推出的LayerNorm和FusedLSTMKernel…