使用 CUDA 合并对二维数组的内存访问
Coalesced memory access to 2d array with CUDA
我正在处理一段 CUDA C++ 代码,需要每个线程实质上通过行优先和列优先访问全局内存中的二维数组。具体来说,我需要每个线程块:
- 生成它自己的一维数组(比方说,gridDim # of elements)
- 将这些写入全局内存
- 读取每个写入数组的第n个元素,其中n是块ID。
在我看来,只有写入或读取可以合并,而另一个将为每个元素访问一个单独的缓存行(并且执行得非常糟糕)。我读到纹理内存有一个二维缓存机制,但不知道它是否可以用来改善这种情况。
顺便说一句,我使用的是 GTX 770,因此它是具有计算能力 3.0 的 GK104 Kepler 卡。
如有任何帮助或建议,我们将不胜感激!谢谢。
在这种情况下,值得在每个访问模式之间进行转置操作以将数据置于最佳顺序。可以编写转置本身以使用 SMEM,以便合并其读取和写入。
或者(克里斯蒂安在他的评论中提到)如果你能够让你的次优传递做一些类似于 SMEM 转置的第一步,你可以跳过完整的转置,只使用它的概念来优化一下。
事实证明我的算法本身必须重新设计,因为使用上述方法无法避免非合并操作对性能的影响。相反,我能够合并每个块上的值并使用更少的全局内存。
附带说明一下,我对合并操作和非合并操作进行了一些实验,以确定它会导致多少减速。事实证明,非合并读取比合并慢大约 10 倍,而非合并写入大约慢 15 倍。所以我想非合并读取是两害相权取其轻...
我正在处理一段 CUDA C++ 代码,需要每个线程实质上通过行优先和列优先访问全局内存中的二维数组。具体来说,我需要每个线程块:
- 生成它自己的一维数组(比方说,gridDim # of elements)
- 将这些写入全局内存
- 读取每个写入数组的第n个元素,其中n是块ID。
在我看来,只有写入或读取可以合并,而另一个将为每个元素访问一个单独的缓存行(并且执行得非常糟糕)。我读到纹理内存有一个二维缓存机制,但不知道它是否可以用来改善这种情况。
顺便说一句,我使用的是 GTX 770,因此它是具有计算能力 3.0 的 GK104 Kepler 卡。
如有任何帮助或建议,我们将不胜感激!谢谢。
在这种情况下,值得在每个访问模式之间进行转置操作以将数据置于最佳顺序。可以编写转置本身以使用 SMEM,以便合并其读取和写入。
或者(克里斯蒂安在他的评论中提到)如果你能够让你的次优传递做一些类似于 SMEM 转置的第一步,你可以跳过完整的转置,只使用它的概念来优化一下。
事实证明我的算法本身必须重新设计,因为使用上述方法无法避免非合并操作对性能的影响。相反,我能够合并每个块上的值并使用更少的全局内存。
附带说明一下,我对合并操作和非合并操作进行了一些实验,以确定它会导致多少减速。事实证明,非合并读取比合并慢大约 10 倍,而非合并写入大约慢 15 倍。所以我想非合并读取是两害相权取其轻...