CUDA:为什么位运算符有时比逻辑运算符更快?

11

当我试图从内核中挤出最后一点性能时,通常我会发现使用位运算符(&|)替换逻辑运算符(&&||)会使内核速度稍微快一点。这是通过在CUDA Visual Profiler中观察内核时间摘要得出的。

那么,在CUDA中为什么位运算符比逻辑运算符更快呢?我必须承认,它们并不总是更快,但很多时候它们确实更快。我想知道是什么魔法赋予了这种加速。

免责声明:我知道逻辑运算符会短路,而位运算符则不会。我很清楚如何误用这些运算符导致错误的代码。我只在保证结果逻辑相同,有加速且加速对我有意义时小心使用此替换 :-)


感谢您提供的优化技巧! - Roger Dahl
罗杰:很高兴能帮忙!当我发现这个时,我也感到惊讶 :-) - Ashwin Nanjappa
3个回答

12

逻辑运算符通常会导致分支,特别是需要遵守短路评估规则时。对于普通的 CPU,这可能意味着分支错误预测,对于 CUDA 来说这可能意味着线程束分歧。位运算不需要进行短路评估,因此代码流程是线性的(即无分支)。


1
此外,对于逻辑运算符而言,非零结果必须设置为1。 - Roger Dahl
1
@Roger:没错,但通常情况下这可以被优化掉,例如如果表达式只是作为条件的一部分使用-结果只需要在被赋值给变量时设置为1。 - Paul R

8

A && B:

if (!A) {
  return 0;
}
if (!B) {
  return 0;
}
return 1;

A & B:

return A & B;

考虑到评估A和B可能会产生副作用(它们可以是在评估时改变系统状态的函数),因此这些是语义。

编译器可以根据A和B的类型和上下文优化的情况,有很多种方式。


1

位运算可以在硬件级别的寄存器中进行。寄存器操作是最快的,特别是当数据可以适合寄存器时。逻辑操作涉及表达式评估,可能不受寄存器限制。通常情况下,&、|、^、>>等是一些最快的操作,并广泛用于高性能逻辑。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接