GPU选购指南:训练ML模型,我必须买RTX3080吗?(12)

此外,你应该知道 GPU 上的最小线程单元是一个包含 32 个线程的包——这被称为 warp 。通常,warp 以同步模式运行——warp 内的线程必须彼此等待 。GPU 上的所有内存操作都针对 warp 进行了优化 。例如,从全局内存中加载的粒度为 32*4 字节,恰好有 32 个浮点数,恰好每个线程一个浮点数 。在串流多处理器(SM,相当于一个 CPU 内核)中,我们最多可以有 32 个 warp=1024 个线程 。SM 的资源被分配给所有活动的 warp 。所以,有时我们想要运行较少的 warp,这样每个 warp 就有更多的寄存器 / 共享内存 / 张量核资源 。
对于下面的两个例子,我们假设计算资源相同 。对于这个 32×32 矩阵乘法的小例子,我们使用 8 个 SM(约为 RTX 3090 的 10%),每个 SM 8 个 warp 。
矩阵乘法(无张量核)如果我们想做一个 A*B=C 的矩阵乘法,其中每个矩阵的大小是 32×32,那么我们会希望将反复访问的内存加载到共享内存中,因为它的延迟大约是前者的 1/10(200cycle vs 20 cycle) 。通常,共享内存中的内存块被称为 memory tile 或只是 tile 。使用 2*32 warp,可以并行地将两个 32 *32 浮点数矩阵加载到共享内存块中 。我们有 8 个 SM,每个 SM 有 8 个 warp,因此,得益于并行化,我们只需要执行一次从全局内存到共享内存的顺序加载,这需要 200 个 cycle 。
为了进行矩阵乘法,我们现在需要从共享内存 A 和共享内存 B 加载一个包含 32 个数值的向量,并执行一个融合乘加(FFMA) 。然后将输出存储在寄存器 C 中 。我们将工作划分为这样一种方式,即每个 SM 做 8x 点积(32×32)来计算 C 的 8 个输出 。为什么这恰好是 8(在旧算法中是 4)有很强的技术性 。这一点,我建议你阅读 Scott Gray 关于矩阵乘法的博文来理解 。这意味着,我们有 8 次共享内存访问,每次 20 个 cycle,8 次 FFMA 操作,每次 4 个 cycle 。因此,总开销是:

200 cycle(全局内存)+ 8*20 cycle(共享内存)+ 8*4 cycle(FFMA)= 392 cycle
下面让我们看下使用张量核时需要多少开销 。
矩阵乘法(有张量核)利用张量核,我们可以在一个 cycle 内执行 4×4 矩阵乘法 。要做到这一点,我们首先需要把内存读到张量核中 。与上面类似,我们需要从全局内存(200 cycle)读取数据并存储在共享内存中 。要做一个 32×32 矩阵乘法,我们需要执行 8×8=64 次张量核运算 。一个 SM 有 8 个张量核,因此,我们总共有 64 个张量核——这正是我们需要的数量!我们可以通过 1 次内存传输(20 cycle)将数据从共享内存传输到张量核,然后进行 64 次并行张量核操作(1 cycle) 。这意味着,在这种情况下,张量核矩阵乘法的总开销为:
200 cycle(全局内存)+ 20 cycle(共享内存)+ 1 cycle(Tensor Core)= 221 cycle
因此,我们通过张量核将矩阵乘法的开销从 392 个 cycle 大幅降低到 221 个 cycle 。在这种情况下,张量核降低了共享内存访问和 FFMA 操作的成本 。
在这个例子中,有和没有张量核都大致遵循相同的计算步骤,请注意,这是一个非常简化的例子 。在实际情况下,矩阵乘法涉及到更大的共享内存块,计算模式也稍微不同 。
不过我相信,通过这个例子,我就很清楚为什么内存带宽对于配备张量核的 GPU 来说如此重要 。在使用张量核进行矩阵乘法时,全局内存是 cycle 开销中最重要的部分,如果可以降低全局内存延迟,我们甚至可以拥有速度更快的 GPU 。要做到这一点,我们可以通过增加内存的时钟频率(增加每秒 cycle 数,但也会增加发热和电量消耗)或增加每次可以转移的元素数量(总线宽度) 。
内存带宽从上一节我们已经看到,张量核非常快 。事实上,它们大部分时间都是空闲的,因为需要等待数据从全局内存读到共享内存 。例如,在 BERT 大型训练中,它使用非常大的矩阵——对于张量核来说,越大越好——我们的 Tensor Core TFLOPS 利用率大约为 30%,也就是说,70% 的时间张量核都是空闲的 。
这意味着,当比较两个具有张量核的 GPU 时,GPU 性能的最佳指标之一就是它们的内存带宽 。例如,A100 GPU 的内存带宽为 1555 GB/s,而 V100 的是 900 GB/s 。因此,基本可以估计 A100 的速度是 V100 的 1555/900 = 1.73 倍 。
共享内存 / L1 缓存大小 / 寄存器由于内存传输到张量核是性能的限制因素,所以我们正在寻找其他可以提升内存到张量核传输速度的 GPU 属性 。这和共享内存、L1 缓存以及使用的寄存器数量有关 。理解存储层次结构如何带来更快的内存传输,有助于理解矩阵乘法在 GPU 上如何执行 。


推荐阅读