因此,我有一个在晶格上使用动力学蒙特卡罗的代码来模拟某些东西。我正在使用 CUDA 在我的 GPU 上运行此代码(尽管我相信同样的问题也适用于 OpenCl)。
这意味着我将格子划分为小的子格子,每个线程都在其中一个子格子上运行。由于我正在进行 KMC,每个线程都有以下代码:
While(condition == true){
*Grab a sample u from U[0,1]*
for(i = 0; i < 100;i++){
*Do some stuff here to generate A*
if(A > u){
*Do more stuff here, which could include updates to global memory*
break();
}
}
}
A 对于不同的线程是不同的,u 也是不同的,100 只是一个随机数。在代码中,这可能是 1000 甚至 10000。
那么,当线程通过该 if 时,我们不会出现分支分歧吗?这会对性能产生多严重的影响?我知道答案取决于 if 子句中的代码,但是当我添加越来越多的线程时,这个问题将如何扩展?
任何关于我如何估计绩效损失/收益的参考也将受到欢迎。
Thanks!
GPU 以 32 个线程为一组运行线程,称为扭曲。发散只能发生在扭曲内。因此,如果您能够以这样的方式安排线程if
条件在整个扭曲中以相同的方式评估,没有分歧。
当一个问题出现分歧时if
,从概念上讲,GPU 只是忽略来自线程的结果和内存请求。if
条件是假的。
那么,说if
评估为true
对于特定经纱中的 10 根纱线。当里面if
,warp 的潜在计算性能从 100% 降低到 10 / 32 * 100 = 31%,因为 22 个线程被禁用if
本来可以做工作,但现在只是在亚空间中占据空间。
一旦退出if
,禁用的线程再次启用,并且扭曲以 100% 的潜在计算性能继续进行。
An if-else
行为方式大致相同。当扭曲达到else
,启用的线程if
变为禁用,并且禁用的变为启用。
In a for
对于 warp 中的每个线程循环不同次数的循环,当线程的迭代计数达到设定数量时,线程将被禁用,但整个 warp 必须保持循环,直到具有最高迭代计数的线程完成。
当考虑潜在的内存吞吐量时,事情有点复杂。如果算法受内存限制,则可能不会因扭曲发散而导致太多或任何性能损失,因为内存事务的数量可能会减少。如果 warp 中的每个线程都从全局内存中完全不同的位置读取(对于 GPU 来说这是一个糟糕的情况),则每个禁用线程都可以节省时间,因为不必执行它们的内存事务。另一方面,如果线程正在读取已针对 GPU 访问进行优化的数组,则多个线程将共享单个事务的结果。在这种情况下,将从内存中读取用于禁用线程的值,然后与禁用线程可能完成的计算一起丢弃。
因此,现在您可能已经有了足够的了解,能够对扭曲发散将影响您的性能的程度做出很好的判断。最坏的情况是扭曲中只有一个线程处于活动状态。那么您将获得 1/32 = 3.125% 的计算限制性能潜力。最好的情况是 31/32 = 96.875%。为if
这是完全随机的,你得到 50%。如前所述,内存限制性能取决于所需内存事务数量的变化。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)