关于warp中遇到Branch Divergence的执行情况

CUDA官方的文档[1]里原文是: "If threads of a warp diverge via a data-dependent conditional branch, the warp serially executes each branch path taken, disabling threads that are not on that path, and when all paths complete, the threads converge back to the same execution path. "请教学长后了解到path taken中taken的意思是和汇编里jump大概意思,也就是说这个path是指分支中需要跳转后的地址(例如if-else分支中else后的代码段就是thepath taken)。按照这个意思的话,当一个warp里的threads遇到分支时,跳到path taken的theads会先同时执行,然后再同时执行threads that are not on that path。

如果是一个32分支的条件语句[2]

if(t==c[0]) {...}
else if(t==c[1]) {...}
else if(t==c[2]) {...}
....
else if(t==c[31]) {...}


threadId为31(最远的else,path taken)的会先执行,然后是30,29,28...0号的线程顺序执行


对于另外一个代码段[2]

int __shared__ var=0;
while (var!=tid) ;  /*注意这里循环体为空*/
/*reconvergence point*/
var++;

按常理来说这段代码应该会正常运行,但是实际运行中会deadlock。文章里给出的解释是“When thread 0 reaches the reconvergence point, the other (serialized) path is executed. Thread 0 cannot continue and increment sharedvar until the rest of the threads also reach the reconvergence point. ”。一开始想不明白为什么thread 0会卡在reconvergence point等待其他线程到达才会继续往下执行,后来谷歌到一遍关于NIVIDIA GPU架构的笔记[3]有句话“When reconvergence point reached, execution switches back to other path (say, not-taken). When reconvergence point reached a second time execution continues at reconvergence instruction and beyond.”大意是说reconvergence point要到达第二次的时候之前的线程才能继续execution下去。这个笔记貌似不是官方的也不清楚作者是追,可信度不知道,但是刚好可以解释出现deadlock的原因,姑且先就这么认为吧,等以后遇到相关问题再继续研究。


在一个CUDA教学的PPT[4]里也提到:"warp内指令时自动同步的,不需要__syncthreads(),不需要if(tid<3)",我的理解是如果warp内遇到分支,则在分支结束后warp会自动同步指令,分支内是按照先taken顺序执行,这样也解释了上面例子为什么会出现deadlock。




参考:

[1] http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html

[2] Demystifying GPU Microarchitecture through Microbenchmarking

[3] www.ece.lsu.edu/gp/notes/set-nv-org.pdf

[4] NVIDA CUDA超大规模并行程序设计训练课程 清华大学邓仰东

你可能感兴趣的:(CUDA)