对开发者而言,应该尽量避免在同一个Warp中有不同的执行路径。当必须写分支语句时,尽量让分支宽度大于WarpSize,即不以Thread为分支单位,而是以Warp为分支单位,这样就能保证同一个Warp内部不会出现分支。
请问如果分配线程块 block(256)
核函数中是
int warpIdx = threadIdx.x/32;
if(warpIdx < 2){
执行语句1;
}else{
执行语句2;
}
代码是以warp为分支单位,那这种情况下if和else可以同时运行吗?
即现在有一个需求,想让线程块中一部分线程来执行计算,另一部分线程来把数据从全局内存搬运到共享内存,请问我可以通过上述if-else达到这两种需求同时运行的效果吗?
关于你的几个问题:
(1)“当必须写分支语句时,尽量让分支宽度大于WarpSize”---我猜测你的正确意思应该是分支宽度是warpSize的倍数。
(2)“那这种情况下if和else可以同时运行吗”--如果编译器生成了常规的跳转指令,同时2个warp执行到了不同分支的位置,则在SM有多个scheduler的情况下,的确2个warp可能在同时执行这2个不同的代码路径。
(3)“即现在有一个需求,想让线程块中一部分线程来执行计算,另一部分线程来把数据从全局内存搬运到共享内存,请问我可以通过上述if-else达到这两种需求同时运行的效果吗?”---这个的确可以,前人有一篇老文章,讲述了通过"warp specilization来执行特殊的载入任务,一个warp为其他warp服务“(大致意思,原文记不清了,你可以搜搜对应的英文原文”。
不过考虑到现在已经有了异步载入指令(例如你的8.6计算能力的RTX30卡),和最新9.0计算能力的内嵌在SM内部的微型DMA引擎,都可以完成你设想的载入global->shared的任务,你的独立使用1个warp来进行的主意,可能没有太大的用途。我建议你使用异步载入,手册有介绍(针对8.6的,9.X的你还得等)。