Algorithm 重写if语句以避免分支是否值得?

Algorithm 重写if语句以避免分支是否值得?,algorithm,branch,Algorithm,Branch,最近,我意识到我做了太多分支,而不关心它对性能的负面影响,因此我决定尝试学习所有关于不分支的知识。这里有一个更极端的例子,试图使代码具有尽可能少的分支 因此,对于代码 if(expression) A = C; //A and C have to be the same type here obviously 表达式可以是A==B,或Q取决于编译器、指令集、优化器等。当使用布尔表达式作为int值时,例如(A==B)*C,编译器必须进行比较,并根据结果将一些寄存器设置为0或1。

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

因此,对于代码

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

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

天哪,不,不要这样做

任何“因为分支而惩罚你很多”的人都希望你因为使用了如此糟糕的东西而被解雇

这有多可怕,让我来数一数:

  • 无法保证您可以将一个数量(例如,
    C
    )乘以一个布尔值(例如,
    (a==B)
    产生
    true
    false
    )。有些语言会,有些不会
  • 随便阅读它的人都将观察一个计算,而不是一个赋值语句
  • 您将用两个比较、两个乘法、一个减法和一个加法替换一个比较和一个条件分支严重非最佳
  • 它只适用于整数值量。用各种各样的浮点数或对象试试这个方法,如果你真幸运的话,它会被编译器/解释器/任何东西拒绝

  • <>你只应该考虑如果你已经分析了程序的运行时属性,并确定这里有一个频繁的分支错误预测,这就造成了实际的性能问题。它使代码变得不那么清晰,而且一般来说它的速度并不明显(在您感兴趣的情况下,这也是您必须测量的)。

    在进行研究后,我得出结论,当出现瓶颈时,最好包括定时分析器,因为这类代码通常不可移植,主要用于优化

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

    我用C++测试了我的代码,因为额外的算术,我的实现实际上是慢的。 然而! 对于下面的这种情况

    if(expression)     //branched version
      A += C; 
    //OR
    A += (expression)*(C); //non-branching version
    
    时间就是这样。 分支排序列表大约需要2秒钟

    分支未排序列表约为10秒

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

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

    考虑我所提出的实施方案可能更有价值。
    **同样,它主要是针对被视为瓶颈的区域**

    这里应该是什么类型的A、B和C?你能用一个布尔值乘以C吗?为此,假设它们都是整数。谢谢首先,您应该更仔细地考虑代码的结构,以查看条件是否可以简化,因为每个条件块都是您必须结合其他块进行测试的另一条路径。之后,对于简单的情况,您应该首先检查是否有编译器开关(例如,GCC中的
    -mcpu
    -mtune
    ),这将鼓励编译器自动执行此操作。如果您必须手工编写一个无分支条件的代码,那么最好使用
    a^=-(a==B)和(C^B),但您仍然希望编译器在内部对
    a==B
    进行无分支计算。当然,您可以将其分解为
    a+=(a==B)*(C-a)
    ?哦,感谢您的改进!但是,有些编译器并不一定擅长这些优化。无论您想要分支代码还是HACKY代码,都要看您需要多少性能和代码如何使用。值得注意的是,这主要是我在VisualStudio环境下对C++进行测试后得出的结论。因此,在进行此类优化时,应始终使用定时探查器
    if(expression)     //branched version
      A += C; 
    //OR
    A += (expression)*(C); //non-branching version