3

最近我意识到我做了太多的分支而不关心它对性能的负面影响,因此我下定决心尝试学习所有关于不分支的知识。这是一个更极端的情况,试图使代码具有尽可能少的分支。

因此对于代码

if(expression) 
  A = C;       //A and C have to be the same type here obviously

表达式可以是 A == B 或 Q<=B,它可以是任何解析为真或假的东西,或者我想在这里的结果是 1 或 0 来考虑它

我想出了这个非分支版本

A += (expression)*(C-A);   //Edited with thanks

所以我的问题是,这是一个最大化效率的好解决方案吗?如果是,为什么,如果不是,为什么?

4

4 回答 4

6

取决于编译器、指令集、优化器等。当您使用布尔表达式作为int值时,例如,(A == B) * C编译器必须进行比较,并根据结果将某些寄存器设置为 0 或 1。一些指令集除了分支之外可能没有任何方法可以做到这一点。一般来说,最好写简单、直接的代码,让优化器自己解决,或者找一个分支较少的不同算法。

于 2013-06-06T01:11:38.697 回答
2

天哪,不,不要那样做!

任何“因为分支而惩罚[s] [你] ”的人都希望你因为使用了那么糟糕的东西而打包。

有多可怕,让我数一数:

  1. 不能保证您可以将一个数量(例如, C)乘以一个布尔值(例如, (A==B)yieldtruefalse)。有些语言会,有些不会。
  2. 随便阅读它的任何人都会观察计算,而不是赋值语句。
  3. 您正在用两个比较、两个乘法、一个减法和一个加法替换一个比较和一个条件分支。 严重不理想。
  4. 它仅适用于整数数量。尝试使用各种浮点数或对象,如果你真的很幸运,它会被编译器/解释器/任何东西拒绝。
于 2013-06-06T01:29:08.280 回答
0

只有在分析了程序的运行时属性并确定这里经常出现分支错误预测并且这会导致实际的性能问题时,才应该考虑这样做。它使代码变得不那么清晰,并且通常它会更快并不明显(在您感兴趣的情况下,这也是您必须测量的东西)。

于 2013-06-06T02:27:59.110 回答
0

经过研究,我得出的结论是,当有瓶颈时,最好包含定时分析器,因为这类代码通常不可移植,主要用于优化。

在阅读下面的以下问题后,我得到了一个确切的例子

为什么处理排序数组比处理未排序数组更快?

我使用它在 C++ 上测试了我的代码,由于额外的算术,我的实现实际上更慢。

然而!对于下面的这种情况

if(expression)     //branched version
  A += C; 
//OR
A += (expression)*(C); //non-branching version

时间就是这样。分支排序列表大约需要 2 秒。

未排序的分支列表大约需要 10 秒。

我的实现(无论是排序的还是未排序的)都是 3 秒。

这表明,在未排序的瓶颈区域中,当我们有一个可以简单地用单个乘法替换的琐碎分支时。

考虑我建议的实现可能更值得。**再次主要针对被视为瓶颈的领域**

于 2013-06-07T21:47:39.563 回答