1

我是 GPU 编程的新手,并试图首先确定特定产品是否值得移植到 GPU。算法中的一个主要步骤需要计算大量Frobenius 乘积(类似于点积,但在矩阵上——逐元素乘法,然后对乘积求和。)

数据结构使我可以将所有内容存储在 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) 合并内存准则是否也适用于从共享内存移回全局内存?

4

1 回答 1

3

1) 正确。一次(双精度)乘法是一次浮点运算,或 FLOP。如果你需要从内存中加载两个操作数,那就是 1/16 FLOPS/byte。但是,如果您需要m个矩阵与其他n 个矩阵的乘积,理想情况下您会得到 ( m * n ) / (8 * ( m + n )) FLOPS/byte,并且对于足够大的mn,您会遇到算术上的密集问题。

2) 合并的内存读取有助于实现(接近,例如 80%)指定的内存带宽。现在假设您确实可以实现这些,计算能力 2.0 GTX 580 上的缓存对此有很大帮助。

3)这取决于。GPU 的内存带宽也大约是 CPU 的 10 倍,因此即使是内存受限的任务也可以更快。

4)是的,他们这样做(对于移动的全局内存方面)。共享内存有不同的规则来避免“银行冲突”。但是现在不要为此烦恼,因为共享内存访问比全局内存访问快几个数量级,所以几乎只有后者才是重要的。

最重要的因素是:需要相乘的矩阵来自哪里?如果它们来自主机,需要通过 PCIe 传输,这是一种损失,产品最好在 CPU 上计算。如果矩阵可以在 GPU 上生成,那很好,您将从更高的内存带宽中受益。如果您可以在生成矩阵的同时动态计算点积,而无需将它们存储在片外内存中,那么 GPU 将会大放异彩。尽管这将取决于计算矩阵的效率,但点积可能只是一个很小的“后果”。您真的确定产品的计算是您最耗时的步骤吗?

于 2013-06-05T01:19:35.417 回答