rt,如果我要对一个M大小的一维数组求和,用规约进行应该是可以的。但是现在遇到个问题,比如我数组大小为962,那么第一次取一半就是481,如果在取一半就是240,但是这里就有个数据被忽略了。。请问一下怎么避免这种情况。。谢谢
LZ您好:
1:像您这样每次线程数折半进行并行规约的话,您的数据需要是2的幂次才能保证直接这样处理得到正确结果。您可以考虑在第一次规约的时候做一下特别处理,使得求和之后还剩下2的幂次个数据。比如您的数组,开始有962个数据,小于962的最大的2的幂次为2^9=512。962-512=450,那么您可以先将0~449号线程拿出来将第512~961(数组编号从0开始)位置的数据累加到0~449位置。
之后您可以放心地进行线程数折半的并行规约了。
2:以及,您也可以查阅一下相关的资料,也有可以自适应任意数的并行规约的格式,但是上述方式可能较为直接和简洁一些。
3:以及这种线程数每次折半的并行规约算法一般比较适合于大量数据规约的扫尾工作。因为每次工作的线程数量会减半,那么很快地每个block里面都只剩下少量的线程在干活,但是block又无法结束以释放资源,这是有损GPU效率的。对于大量数据的情况,可以有其他的并行规约格式。
大致如此,供您参考。
感谢您周末来访,祝您编码顺利~
谢谢ice斑竹的解答。我这里的数据应该差不多是4040700*sizeof(float)的大小,这个数据到底是大还是小了?还有我现在接触到的资料好像都是折半进行规约的。。自适应任意数规约的资料不知道斑竹有没有推荐的?谢谢
LZ您好:
1:您这个算有一定规模了。如果您每block上512线程计算512个数据的话,需要2000多个block了。您可以考虑安排数十个block,每个block完成总数据量除以block数目的这些数据量。假定每个block仍为512线程,并假定每个block需要计算512*N个数的规约相加(实际做的时候你需要自己处理一下不整除的情况)。
那么您可以
a:循环N次,每次读取512个数据,并由每个线程将自己读到的数据累加在自己的寄存器里面。
b:block同步。
c:此时512*N个数据已经规约相加得到512个数据,下面进行shared memory的折半规约。512个线程将自己的累加结果复制到shared memory。
d:block内线程同步以保证数据复制完成。
e:标准的512线程shared memory折半规约。
f:规约得到的最后结果由线程0原子累加到global memory。
这应该是一个较为合理的实现。
2:那个自适应数(不要求是2的幂次)的折半规约的资料我这里没有,这个是之前在本版某帖见到的,距现在有数个月了,已经不记得详情。
大致如此,祝您编码顺利~
————————————————————————————————————————
调整了一下排版。