我遇到一个小问题,请版主指点。
我有一个数组,例如 a[8]={1,1,1,1,1,1,1,1};
现在要从第一个元素开始依次加到后面去。结果为b[8]={1,2,3,4,5,6,7,8};
我试了一天,也没想到怎样将这个算法并行化。归约求和只能得到一个总和,不能实现累加效果。
这个算法如何并行化,请版主赐教。
我也没有好办法。
但如果您有大量的a[8]这样的数组,例如10000批。那么每个里面可以依然进行普通的累加(串行的),然后这10000组之间在并行(还有一些优化细节,例如访存的合并性等)。
但回到您的这个a[8], 后面一个需要加上前面的所有的总和,我没有好办法。
其他会员,版主,NVIDIA原厂支持和总版主也许能为您想想办法。
实际上我的数组是128个元素,而不是8个。问题在于我这个累加的步骤被夹在两个并行性比较好的步骤之间,如果划分为三个kernel,又要花销大量的数据传输时间,并且每个kernel的任务被划分得很少,想想也不划算。
其实这个真没好办法,如果你数据份数大了,吞吐率自然就上去。
但如果真的是很小的数据规模,只有128个元素的话,如果不在乎多于的运算能力的浪费(例如您此时只需要运行这个128元素计算的kernel, 其他kernel都在等待)。您可以考虑增加运算量的方式,来尽快得到结果(尽量低的延迟)。
例如第40个元素,可以对0-39号元素进行规约,然后累加到第40号元素上。
同时,例如第90号元素,也在同时对0-89号元素进行规约,然后累加到第90号元素上。
这样每个元素,可以用一个block负责,此block对该元素之前的所有元素进行规约。
而block和block之间是独立的,各自负责各自的元素。
这样虽然block和block之间有重复的计算,但最坏的情况(第128号元素的那个block), 也不过需要约log2(128) = 7次规约即可。
这种可能让GPU被全面占用,可以尽快的让你得到结果,代价则是有大量的浪费计算。
但如果此时GPU不需要计算其他结果,你直接这样来应该是时间最快的。
但这个只是对你的[128]的数组来说,数据规模一大,或者GPU不允许被这样的浪费。
则您不能使用这个方案。
也许其他有人更好的方案。
如果你含有128个元素数组的个数巨大的话数据传输那点时间不会有太大的影响。
如果量不大直接串行或者omp,没必要一定上cuda
楼主此步骤可能是处理2个kernel之间的中间结果的。
数据可能本来就在device上。
此时可能传回来串行计算效果不好,不如就地计算了。无论是串行还是横扫的方法。
您这种方法会有大量的重复计算,而且听起来编程也不好编,我还是尝试让一个线程串行累加一个数组,然后启动大量线程吧。看看效果怎样
看来这种运算的并行性确实太低了,我的数据是在DEVICE上,不想传回CPU。
我的数据是已经在显存里了,并行性这么差的运算,如果是在HOST端,我就不传进去了。
谢谢各位的讨论