大多数情况下,在CUDA或OpenCL程序中需要分支,例如:
for (int i=0; i<width; i++)
{
if( i % threadIdx.x == 0)
quantity += i*i;
}
代码总是(或至少在大多数情况下)以非分支样式重写:
for (int i=0; i<width; i++)
{
quantity += i*i* (i % threadIdx.x != 0);
}
权衡似乎是在单个warp槽中运行而不是在所有线程上执行更多计算(在第二种情况下,总和总是执行,有时值为零)
假设分支操作将为每个可能的分支采用多个warp插槽,可以预期第二个将始终优于第一个,现在我的问题是;我是否可以依赖编译器优化1)2)只要它有意义,或者没有广泛适用的标准,这意味着如果没有尝试和分析,一般不能确定哪一个更好?
答案 0 :(得分:3)
模数运算相当昂贵:我有理由相信在模数中加入会比使用只有1个线程执行的单个指令花费更多时间。您的单个分支语句if
没有else
,只会挂起其他线程,而if语句正在执行。因为gpus针对非常快速的上下文切换进行了优化,所以应该花费很少的成本。
建议您不要使用长分支语句:GPU上的串行计算过多(即一个线程完成所有工作)否定了并行性的优势。
答案 1 :(得分:1)
根据我的经验 - 完全由编译器编写者来优化这些边缘情况。
那么我能想到1)无法转向2)的任何情况吗?这是一个:我已经编写了内核,每10个线程或类似的东西运行某些计算部分更有效率,在这种情况下,即使存在可以进行数学运算(除法除法),也无法推断出这样的优化产生相同的结果,不管条件与“全部运行,但产量为零的结果”。
然而,即使检查threadId == 0是一个常见的场景,我也不知道它是否真的被优化了。我敢打赌它取决于实现甚至设备本身(CPU与GPU)。
你必须尝试它才能真正找到最有效的方法,不仅仅是因为上面的原因,还因为工作调度程序可能会因为调度/启动/停止一组线程的成本而有所不同反对让它们全部运行(并且大多数都提供零/同一性结果)。
希望这有帮助!
答案 2 :(得分:0)
我对CUDA没有太多记忆,但为什么不对你的循环进行并行化?您应该使用原子操作[1]来添加计算。我希望这能帮到您!对不起,如果不是这样的话。