rt,如果我有个二维的线程网格比如是400001000,在每个网格块中都有一个共享的值设为val,想找到二维网格中每行中val的最大值,现在有下面几个问题:
1):在计算能力3.0的卡上能不能有400001000大小的线程网格,编程指南上面x,y,z的最大尺寸为:2^31-1,65535,65535,感觉怎么这么大啊?是我理解有问题还是真心有这么多。。
2):如果要找到二维网格中每行val的最大值,怎么保证所有行的val都是计算完成了的呢,好像block中不能同步。。这个怎么搞?难道弄一个全局存储器,等计算val的函数完成后再来求最大值么?就是用核函数执行完成来保证block同步。。概念不是很明确。。还麻烦斑竹指点一下。。谢谢
LZ您好:
您的题目和叙述中似乎混淆了以下3个概念,导致我无法理解您的意图。
1)block,如果是CUDA中的block,那么当前硬件支持下最大block为1024线程。
2)grid,当前硬件最高支持x方向2^31-1个block(注意是以block为单位的,而不是以thread为单位),以及y和z方向最大65535个block。
3)您需要处理的数据的规模和格式实际与grid,block形状并无直接关系。您可以考虑一个线程处理一个点的数据,使得线程数目和数据点数相同,也可以考虑一个线程处理多个点数,这样线程规模可以相应减少。这完全取决于您的实现方法。
回到您的问题
1:这个请根据programming guide的Appendix.F自行查证,不再赘述。
2:如果您这里的“二维网格”指的是您的数据形式,那么您只需要设法按照行判断并求最大值就行了,理论上一个线程也可以计算一行的。比较快的方法是在每一行中规约求最大值。
同时,您指出的“在每个网格块中都有一个共享的值设为val”实在无法理解,因为您“网格块”说的有多种歧义,以及“共享值”是打算放在shared memory中么?以及为何打算这样办?以及您的算法意图为?
我实在无法自动脑补更多信息了,请您将问题清楚地重新叙述一下,谢谢合作。
祝您好运~
嗯。。谢谢斑竹的解答。。
1:我的意思是建立个二维grid,大小为400001000,就是一共有400001000这么多个block,只不过以二维形式组织起来的;
2:我现在是打算用遗传算法来做图像相关的初值搜索,对于每图像设置1000个个体,每个个体要执行http://cudazone.nvidia.cn/forum/forum.php?mod=viewthread&tid=7019这个类似的程序(这里一个个体就相当于执行一次程序,就是说每个上面的代码执行1000遍),因为考虑到计算量比较大,所以打算每个个体做为一个block计算,因为有1000个个体,所以需要1000个block,执行完成后要找出里面的这1000个里面相关系数的最大值。这里就是我讲的“在每个网格块中都有一个共享的值设为val”,我是打算用这个val来保存相关系数。3:如果相关系数大于某个值比如0.95,就结束这1000个块,否则就通过迭代循环。我一共有40000个图,所以一共要申请40000*1000个block。
4:现在遇到的问题是这样的,这1000个个体想当做线程来处理,感觉计算量又太大(就是串行执行上面链接的程序),如果每个当做block来处理,同步这种个体的通讯又不好做。。头痛是死了。。麻烦斑竹指教。。
LZ您好:
1:这是可以的。
2:首先需要说明的是,我不保证您对遗传算法的说明和实现是正确的。此外,您考虑使用1000个block来完成您的某项任务这个是可以的(以及,完成1000组数据的处理,并非一定需要1000个block)。
这里,您1000个相关系数的最大值要这些block全部都计算完成的时候才能得到,此时block们已经相继死去,所以这个“共享的值”是算法逻辑上要求全局可见的,只能放在global memory上。如果放在各个block 的shared memory上,那么在block死去的时候,也就消失了。
以及,这个实现起来没什么难度的,您可以每个block保存自己的结果到global memory的一个数组里面,所有的block结束以后,重新启动一个kernel,进行扫尾工作,求出相关系数的最大值。
此外,需要多说一句的是,据我所知,遗传算法是某种迭代进化算法,要迭代足够多的步数才能得到结果,您这里可能值叙述了其中一步的内容,实际上每步还需要根据前面的结果,计算适应度函数,杀掉一批个体,繁殖和变异一批个体(精英法则),再继续计算。
(未完待续)
对哦。。遗传算法确实需要迭代。。所以现在恼火的是在迭代过程中要涉及到各个个体的通讯。。所以如果把这1000个个体想当做线程来处理,感觉计算量太大(就是串行执行上面链接的程序),如果每个当做block来处理,同步这种个体的通讯又不好做。。头痛是死了。。麻烦斑竹指教。。
3:前面的说法是按照您1:里面主观要求建立40000*1000的二维grid说明的。这里您给出的您的问题描述,因为您要“处理40000个图”。那么,您也可以考虑每个图的1000个block组成一个grid,对应一次kernel启动,然后40000个图用不同的参数启动40000次kernel即可。1000个block一般来说够跑满GPU了。
以及,这样的话,您的kernel可以简单一点,需要顾及的问题少一些。当您需要处理50000个图的时候,简单地循环50000次即可,而无需过多修改。
4:我也无法保证上边的建议确实符合您的实际问题,我只是根据您的叙述在有限的信息下(配合部分自动脑补)做出一定回答,这个是有局限性的,请勿教条化。
大致如此,祝您编码顺利~
嗯。。好的。。谢谢斑竹的指导。。这个建议很好。。嘿嘿。。我先实现一下。。多谢多谢。。这样程序就简化好多了。。
LZ您好:
这个并不难处理的,多个kernel配合即可,比如说使用kernel A和kernel B,前者计算各个个体的相关系数,后者扫尾实现进化算法。
1:kernel A中您可以一个block计算一个个体的一个世代(迭代步)。
2:每个block死亡之前记录下本个体的结果,比如相关系数神马的。
3:启动一个扫尾的kernel B,根据各个block(个体)之前留下的数据,进行遗传算法的那一套进化计算的处理,然后保留处理结果数据。
4:host端循环,根据上述的处理结果,启动kernel A进行新一轮的计算。
大致这样既可,实现细节请您根据实际需要再加以考虑。
祝您编码顺利~
以及,附加说明一下,之所以每次都重启kernel是因为,死去的block是无法唤醒的,所以你不能在所有block的结果都得到的时候,再重新召唤前面死去已久的block出来继续干活,此时只能重启kernel了。