我想知道是否有人可以建议计算CUDA中大量相对较小但不同大小的数组的均值/标准偏差的最佳方法?
SDK 中的并行缩减示例适用于单个非常大的数组,大小似乎很方便是每个块的线程数的倍数,但我的情况却大不相同:
然而,从概念上讲,我有大量的对象,每个对象都包含两个组件,upper
和 lower
,并且这些组件中的每一个都有一个 x
和一个 y
坐标。 IE。
upper.x, lower.x, upper.y, lower.y
这些数组中的每一个的长度都大约为
800
,但它在对象之间(不在对象内)有所不同,例如Object1.lower.x = 1.1, 2.2, 3.3
Object1.lower.y = 4.4, 5.5, 6.6
Object1.upper.x = 7.7, 8.8, 9.9
Object1.upper.y = 1.1, 2.2, 3.3
Object2.lower.x = 1.0, 2.0, 3.0, 4.0, 5.0
Object2.lower.y = 6.0, 7.0, 8.0, 9.0, 10.0
Object2.upper.x = 11.0, 12.0, 13.0, 14.0, 15.0
Object2.upper.y = 16.0, 17.0, 18.0, 19.0, 20.0
请注意,以上只是我表示数组的方式,我的数据并未存储在
C
结构或类似结构中:可以按照我需要的任何方式组织数据。关键是,对于每个数组,都需要计算平均值、标准偏差和最终的直方图,并且在一个特定对象中,需要计算数组之间的比率和差异。我应该如何将这些数据发送到 GPU 设备并组织我的线程块层次结构? 我的一个想法是对所有数组进行零填充,使它们具有相同的长度,并在每个对象上使用一组块,但如果该方法有效,它似乎存在各种问题。
提前致谢
最佳答案
如果我理解正确,您想将 Object1.lower.x 减少到一个结果,将 Object1.lower.y 减少到另一个结果,依此类推。对于任何给定的对象,有四个数组要减少,所有数组的长度都相等(对于对象)。
对此有许多可能的方法,一个影响因素是系统中的对象总数。我会假设这个数字很大。
为了获得最佳性能,您需要最佳内存访问模式,并且您希望避免发散。由于全等数组的数量是 4,如果您采取每个线程执行一个数组的幼稚方法,那么下面不仅您会遇到内存访问不佳的问题,而且 h/w 还需要检查每次迭代中的线程经纱需要执行循环——那些不会被禁用的循环可能会效率低下(尤其是如果一个数组比其他数组长得多,例如)。
for (int i = 0 ; i < myarraylength ; i++)
sum += myarray[i];
相反,如果您让每个经线对一个数组求和,那么不仅效率更高,而且您的内存访问模式也会更好,因为相邻线程将读取相邻元素 [1]。
for (int i = tidwithinwarp ; i < warparraylength ; i += warpsize)
{
mysum += warparray[i];
}
mysum = warpreduce(mysum);
您还应该考虑数组的对齐方式,最好在 64 字节边界上对齐,尽管如果您正在开发 1.2 或更高版本的计算能力,那么这并不像在旧 GPU 上那么重要。
在这个例子中,你将每个块启动 4 个扭曲,即 128 个线程,以及与对象一样多的块。
[1] 你确实说过你可以选择你喜欢的任何内存安排,通常交错数组很有用,这样 array[0][0] 就在 array[1][0] 旁边,因为这意味着相邻的线程可以对相邻阵列进行操作并获得合并访问。然而,由于数组的长度不是恒定的,这可能很复杂,需要填充较短的数组。
关于arrays - 许多小的、大小不等的阵列的 CUDA 减少,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1773700/