Nvidia 架构中的算术强度
Posted
技术标签:
【中文标题】Nvidia 架构中的算术强度【英文标题】:Arithmetic Intensity in Nvidia Architectures 【发布时间】:2013-05-31 13:20:54 【问题描述】:我是 GPU 编程的新手,我正在尝试首先确定某个特定产品是否值得移植到 GPU。该算法的一个主要步骤需要计算大量的Frobenius products(类似于点积,但在矩阵上——一个元素乘法,然后是乘积的总和。)
数据结构使得我可以将所有内容存储在 GPU 的全局内存中,但不能存储在共享内存中。我的理解是,当算术强度(每传输字节的浮点运算)很高时,GPU 表现最好,而点积在这方面表现(相对)较差。我试图弄清楚有多糟糕,并且对一些细节感到困惑。
为了具体化,让我们假设我有 64x64 的双精度条目矩阵。 (它们必须是双精度的。)让我们假设矩阵的布局使得它们也正确对齐。显然,即使每个 SM 一个块,这也太大而无法存储在共享内存中。所以我的想法是“平铺”问题并在每个块中存储每个矩阵的 16x16 平铺;现在我至少可以一次对所有八个块进行操作,为每个产品分配一个线程,计算每个块中的总和等等。
我的问题是:
1) FLOPS/byte 到底是什么意思?或者更准确地说,在这种情况下,双精度乘法需要多少 FLOPS?如果答案是 1,那么似乎我为每个操作移动了 16 个字节,这看起来很糟糕。
2) 这个计算是在合并内存读取的上下文中完成的吗?合并是帮助我还是伤害我?
还有一个更模糊的问题:
3) 这值得吗?
作为参考,我可以使用 GTX 580 进行基准测试和实验,以及 CUDA 4.2,尽管如果有帮助的话,我可能会安装 5.0。如果最近的 Nvidia 架构在某些方面更友好,那么了解这也很有用,尽管我可能无法访问其中一个。
更新:
我仍在研究整个算法,但我有充分的理由相信可以在 GPU 上生成矩阵并将其保存在全局内存中,而无需向 CPU 反复移动任何东西。
我可能不得不重新检查我可以确保合并内存访问的假设。一些矩阵是四维对象的切片;大约 3/4 的矩阵自然会以明显的合并方式访问,而其他 1/4 则不是。我可以通过两次存储大对象来解决这个问题,但这会产生一个新问题:
4) 合并内存准则是否也适用于从共享内存移回全局内存?
【问题讨论】:
【参考方案1】:1) 正确。一次(双精度)乘法是一次浮点运算,或 FLOP。如果你需要从内存中加载两个操作数,那就是 1/16 FLOPS/byte。但是,如果您需要 m 矩阵与 n 其他矩阵的乘积,理想情况下您会得到 (m * n) / (8 * (m + n)) FLOPS/byte,对于足够大的 m 和 n 你有一个算术密集的问题。
2) 合并的内存读取有助于实现(接近,例如 80%)指定的内存带宽。现在假设您确实可以实现这些,计算能力 2.0 GTX 580 上的缓存对此有很大帮助。
3) 视情况而定。 GPU 的内存带宽也大约是 CPU 的 10 倍,因此即使是内存受限的任务也可以更快。
4) 是的,它们确实如此(对于移动的全局内存方面)。共享内存有不同的规则来避免“银行冲突”。不过现在不必为此烦恼,因为共享内存访问比全局内存访问快几个数量级,所以几乎只有后者才是重要的。
最重要的因素是:需要相乘的矩阵来自哪里?如果它们来自主机,需要通过 PCIe 传输,这是一种损失,产品最好在 CPU 上计算。 如果矩阵可以在 GPU 上生成,那很好,您将受益于更高的内存带宽。如果您可以在生成矩阵的同时动态计算点积,而无需将它们存储在片外内存中,那么 GPU 将会大放异彩。尽管这将取决于计算矩阵的效率,但点积可能只是一个很小的“后果”。您确定乘积的计算是您最耗时的步骤吗?
【讨论】:
我将更新问题以解决其中一些问题,但您能否澄清“片外”?显然共享内存是“片上”的。显然,任何脱离 GPU 且可供 CPU 访问的东西都是“片外的”。全局内存呢? 全局内存基本上就是我所说的片外。它有时会伪装成不同的名称,例如“本地内存”(实际上是具有不同寻址方案的全局内存)。因此,为了在我的一般性陈述中包含这些案例,并强调需要在(较慢的)芯片到芯片互连上移动数据,我写了“片外”。 好的,这给了我很多思考,并指出了这部分算法的主要困难在哪里。我相信要点是这部分不会有 10 倍或 100 倍的神奇改进,因为算术强度太低了,但是,我仍然应该得到与卡成比例的性能提升。以上是关于Nvidia 架构中的算术强度的主要内容,如果未能解决你的问题,请参考以下文章