我是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)合并内存指南是否适用于从共享内存移回全局内存?
答案 0 :(得分:3)
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将会闪耀。虽然这将取决于矩阵的计算效率,但点积可能只是一个微小的“后果”。你真的确定产品的计算是最耗时的步骤吗?