【问题标题】:Bit manipulation to replace IF statement and improve performance位操作以替换 IF 语句并提高性能
【发布时间】:2014-05-29 15:55:46
【问题描述】:

我可以替换下面的 IF 语句:

if(condition){
    x += y;
}

与:

x = x + ((y - x) * (condition));

删除分支。

有没有办法避免上面的乘法并用按位操作来代替它以使其更快?

【问题讨论】:

  • 等等,这似乎不对。不应该是x + (y * (condition))吗?
  • 大多数现代处理器提供无分支条件赋值。确保你衡量你最终得到的任何“优化”,以确保你没有放慢速度。
  • @harold 你是对的。操作码相当于if(condition){ x = y };
  • @harold:顺便说一句,它应该是 x + (y * !!(condition)) ,将条件(算术)表达式(如果是这样的话)转换为逻辑 10
  • 在 2 的赞美机器上,您可以 &-condition。但是这种优化对于一个体面的编译器是没有意义的(除了混淆),而且实际上可能会使事情变得更糟。

标签: c++ c performance optimization bit-manipulation


【解决方案1】:

如果没有衡量您的应用程序的预期使用情况,请不要这样做。

为什么不呢。

现代编译器已经可能检测到这些模式并将其转换为条件移动。

现代 CPU 在“时间之前”推测性地运行代码,这可能比复杂的位表达式更快;此外,还有一个分支目标缓冲区,它可以记住本地循环中的决策,然后根据 BTB 提前推测性地运行您的代码。

如前所述:如果没有衡量您的应用程序的预期使用情况,请不要这样做。不要在任意基准上进行测试,这在大多数情况下会产生误导(因此代价高昂)的结果。当然,更喜欢算法和架构优化而不是这种微优化;从长远来看,保持代码可维护通常更便宜;不要在未定义的行为和高度专业化的代码上建立您的业务:

还有。

您的 C 或 C++ 向导是否足以验证您的“优化”的正确性?您是否考虑过无符号溢出和未定义的行为 w.r.t.签名溢出?输入促销信息?

认为答案是否定的,因为您寻求帮助,但没有意识到您的示例中使用的类型至关重要但未提及。

【讨论】:

    【解决方案2】:

    这种优化实际上永远不会提高您的性能。编译器在优化你的代码方面做得比你用这些便宜的技巧做得更好。同样在这种情况下,您实际上会增加代码的复杂性,使其降低效率。将始终必须执行乘法并执行加法。

    【讨论】:

      【解决方案3】:
      if(condition){
          x += y;
      }
      

      if(condition){
          x =x+ y;
      }
      

      所以你可以写成,

      x = x + ((y) * (condition));
      

      仅当条件为01 时。如果条件可以是任何其他值,那么这将不起作用。

      x = x + ((y - x) * (condition));
      

      即使条件只导致01 也不正确,因为它等同于,

        if(condition){
              x=y;
          }
      

      【讨论】:

        【解决方案4】:

        不太确定您是否可以击败整数乘法。在某些处理器上,它需要一个时钟。

        假设 0/1 条件:

        x+= condition * y;
        

        或者:

        x+= (- condition) & y;
        

        【讨论】:

          【解决方案5】:

          在尝试评估之前,您应该为每个变量添加类型。人们可能有不同的假设。另外我的建议是不要那样做。即使你现在做对了,维护起来也将成为一场噩梦。

          【讨论】:

            【解决方案6】:

            将其移一位,将其向上移动到符号位,然后将其向下移动,并一直使用符号扩展名,您会得到全一或全零。

            x + (( y -x) & (((!!condition)<<31)>>31)
            

            不过,这取决于平台。

            【讨论】:

            • 高度专业化、不可读、未定义、高度依赖平台。完全没有解释。
            • "将其移至符号位" 这是未定义的行为。
            • 是的,我并不是说这是一个好主意,但这是那个家伙要求的。
            • @FilipeGonçalves:在这种情况下不是 =) 假设您获得了符号扩展(您在大多数平台上都这样做),您会一直复制符号位 - 所以要么所有位都为零,要么全部为一。
            • (((!!condition)&lt;&lt;31)&gt;&gt;31) 仅当它有位时才给出 1,否则它给出 0,请编辑。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-04-10
            • 2017-02-10
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多