假设由单个 warp 执行的 CUDA 内核(为简单起见)达到if
-else
语句,其中经纱内的 20 个线程满足condition
而 32 - 20 = 12 线程则不会:
if (condition){
statement1; // executed by 20 threads
else{
statement2; // executed by 12 threads
}
根据CUDA C 编程指南:
warp 一次执行一条公共指令 [...] 如果 warp 的线程通过数据相关的条件分支发散,则 warp 串行执行所采用的每个分支路径,禁用不在该路径上的线程,并且当所有路径完成后,线程会聚回相同的执行路径。
因此,这两个语句将在单独的周期中顺序执行。
Kepler 架构的每个 warp 调度器包含 2 个指令调度单元,因此能够在每个周期为每个 warp 发出 2 个独立指令。
我的问题是:在这种只有两个分支的情况下,为什么可以statement1
and statement2
不由两个指令调度单元发出以供warp内的32个线程同时执行,即20个线程执行statement1
而另外 12 个同时执行statement2
?如果指令调度程序不是 warp 一次执行一条公共指令的原因,那么是什么?是只提供32线程宽指令的指令集吗?还是硬件相关的原因?
每条内核指令始终针对扭曲中的所有线程执行。因此,逻辑上不可能同时在同一个线程束内的不同线程上执行不同的指令。这将违背SIMT执行模型GPU 是基于它构建的。对于你的问题:
Kepler 架构的每个 warp 调度器包含 2 个指令调度单元,因此能够在每个周期为每个 warp 发出 2 个独立指令。
...
为什么statement1和statement2不能由两个指令调度单元发出以供warp内的32个线程同时执行,即20个线程执行statement1,而另外12个线程同时执行statement2?
我不确定你是否意识到这一点,但如果statement1
and statement2
计算上是独立的,那么它们可以在一个周期内执行:
- 指示来自
statement1
将在所有线程上执行,
- 指示来自
statement2
由于第二个调度单元,将在调度时的同一周期内对所有线程执行。
这就是 GPU 中分支分歧的一般工作原理,可以找到一些进一步的阅读,例如here。因此,我相信您已经免费得到了您想要的东西 - 两个语句都在同一个周期内执行(或can be).
EDIT:
正如talonmies在评论中所述,可能值得一提的是条件执行,因为它有时有助于防止分支分歧造成的惩罚。有关此主题的更多信息,请参见:在这个所以线程,引用:
对于更简单的条件,NVIDIA GPU 支持 ALU 处的条件评估,这不会导致发散,并且对于整个扭曲遵循相同路径的条件,显然也没有惩罚。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)