GPU 上所需的计算内存比 (OP/B)

Desired Compute-To-Memory-Ratio (OP/B) on GPU

我想了解 GPU 的架构以及我们如何评估我们的程序在 GPU 上的性能。我知道申请可以是:

我还有一个如何计算此 OP/B 指标的示例。示例:下面是用于应用矩阵-矩阵乘法的 CUDA 代码的一部分

for(unsigned int i = 0; i < N; ++i) {
  sum += A[row*N + i]*B[i*N + col];
}

而这个矩阵乘法计算OP/B的方法如下:

如果我们想利用它:

所以如果我清楚地理解这一点,我有以下问题:

It is always the case that the greater OP/B, the better ?

不总是。目标值平衡计算管道吞吐量和内存管道吞吐量的负载(即 op/byte 的级别意味着两个管道都将满载)。当您将 op/byte 增加到超出该级别或某个级别时,您的代码将从平衡切换到计算绑定。一旦您的代码受计算限制,性能将由作为限制因素的计算管道决定。超出此点的额外 op/byte 增加可能不会影响代码性能。

how do we know how much FP operations we have ? Is it the adds and the multiplications

是的,对于您显示的简单代码,它是加法和乘法。其他更复杂的代码可能有其他因素(例如 sincos 等)也可能有所贡献。

作为 "manually counting" FP 操作的替代方法,GPU 分析器可以指示代码已执行的 FP 操作数。

how do we know how many bytes are loaded per FP operation ?

与上一个问题类似,对于简单的代码,您可以"manually count"。对于复杂的代码,您可能希望尝试使用分析器功能进行估算。对于您显示的代码:

sum += A[row*N + i]*B[i*N + col];

必须加载 AB 中的值。如果它们是 float 个数量,那么它们每个都是 4 个字节。总共是 8 个字节。该行代码将需要 1 个浮点乘法 (A * B) 和一个浮点加运算 (sum +=)。编译器会将它们融合成一条指令(融合乘加),但最终效果是您每 8 个字节执行两个浮点运算。 op/byte 是 2/8 = 1/4。在这种情况下,循环不会改变比率。要增加这个数字,您需要探索各种优化方法,例如 a tiled shared-memory matrix multiply,或者只使用 CUBLAS。

(像 row*N + i 这样的操作是 整数 算术,不会影响浮点负载,尽管它们可能在性能方面很重要。 )