避免MISD类型操作的CUDA线程发散

避免MISD类型操作的CUDA线程发散,c,cuda,thrust,C,Cuda,Thrust,作为更大代码的一部分,我有一个CUDA RK4解算器,它并行集成了大量ODE(可以是1000+)。此操作的一个步骤是计算“xdot”,这对于每个方程(或数据元素)是不同的。现在,我有一个开关大小写分支设置来计算内核中每个数据元素的值。所有不同的线程使用相同的3-6个数据元素来计算其输出,但方式不同。例如,对于线程1,它可以是 xdot=数据[0]*数据[0]+数据[1] 而对于线程2,它可能是 xdot=-2*数据[0]+数据[2] 等等。 因此,如果我有100个数据元素,每个元素的执行路径都是

作为更大代码的一部分,我有一个CUDA RK4解算器,它并行集成了大量ODE(可以是1000+)。此操作的一个步骤是计算“xdot”,这对于每个方程(或数据元素)是不同的。现在,我有一个开关大小写分支设置来计算内核中每个数据元素的值。所有不同的线程使用相同的3-6个数据元素来计算其输出,但方式不同。例如,对于线程1,它可以是

xdot=数据[0]*数据[0]+数据[1]

而对于线程2,它可能是

xdot=-2*数据[0]+数据[2]

等等。 因此,如果我有100个数据元素,每个元素的执行路径都是不同的

在这种情况下,有没有办法避免/减少线程发散惩罚?
每个块只运行一个线程会有帮助吗?

每个块运行一个线程只会使您启动的单个扭曲中的31/32个线程为空,并浪费大量的周期和机会来隐藏延迟。无论代码产生多大的分支分歧惩罚,我都不会推荐它


您的应用程序听起来与基本的CUDA编程范式非常正交,并且您真的无法避免分支分歧惩罚。一种可以稍微改善情况的方法是对每个方程的表达式进行一些事先分析,并将具有常用算术项的表达式分组。最新的硬件可以同时运行多个内核,因此将共享类似项的计算分组到不同的内核中并同时启动它们可能是有益的,而不是单个大型内核。CUDA支持C++模板,这可以从一个相对狭窄的基础生成大量内核代码,并使静态逻辑可以评估,这对编译器有帮助。但不要期待奇迹——你的问题可能比GPU(例如英特尔至强Phi)更适合不同的体系结构。

谢谢!我会调查的。至于使用其他架构,这只是问题的一部分。它的其余部分本质上是高度并行的,并且使用CUDA可以很好地扩展。我想看看在这个特殊的部分是否有优化的机会。