【问题标题】:Bitwise manipulation setting variable on a condition条件上的按位操作设置变量
【发布时间】:2014-09-22 04:27:09
【问题描述】:

我在 C/C++ 应用程序中有三个变量 - x、y 和 z。我想设置 x = y,当 z == 3 时。我可以使用乘法来做到这一点:

x = y * (z == 3)

但这是在一个大循环中调用的,IMUL 将占用 4 个 CPU 周期。我希望找到一个需要 1 个 CPU 周期的操作。

编辑:编译器 MSVC 64 位编译、平台 Win 7 64、x86 架构、Ivy Bridge 或 Haswell。

【问题讨论】:

  • 你说的是“会接受”而不是“愿意接受”。您是否查看了生产的组件以确认?
  • z == 3 将解析为布尔值,因此它将为 0 或 1,因此结果将为 y 或 0。
  • 取决于平台,条件可能会更好。例如,大多数 ARM 指令都是有条件的,编译器可以利用这一点。
  • 另外,就像@ddriver 提到的那样,如果z 不是3,那么x 将被设置为0。这是你想要的吗?
  • 在您指定的架构上的整数 ALU 操作应该需要 1 个单周期。 intel.com/content/www/us/en/architecture-and-technology/… - 第 60 页

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


【解决方案1】:

写:

if ( z == 3 )
    x = y * 2;
else
    x = y;

(或您接下来编辑问题的任何其他内容)并激活您的编译器。这就是编译器的用途。你用编译器开关说你想要什么,编译器比你做得更好。

【讨论】:

    【解决方案2】:

    在二进制补码上,表达式:

    (y * (z == 3)) 
    

    等同于:

    (y & -(z == 3))
    

    但是,令人怀疑的是,两者的表现是否会明显不同。考虑以下使用gcc -O3 -S 编译的代码:

    int foo1 (int y, int z) { return y * (z == 3); }
    int foo2 (int y, int z) { return y & -(z == 3); }
    int foo3 (int y, int z) { if (z == 3) return y; else return 0; }
    

    对于foo1()

        xorl    %eax, %eax
        cmpl    $3, 8(%esp)
        sete    %al
        imull   4(%esp), %eax
    

    对于foo2(),还有一条指令(虽然可能更便宜):

        xorl    %eax, %eax
        cmpl    $3, 8(%esp)
        sete    %al
        negl    %eax
        andl    4(%esp), %eax
    

    但是,对于foo3(),你会得到:

        xorl    %eax, %eax
        cmpl    $3, 8(%esp)
        cmove   4(%esp), %eax
    

    虽然它是一个条件移动指令,但代码并没有比这更紧凑。

    【讨论】:

    • 是的,但它将x 设置为y2y,这与问题本身形成对比(当然,这是OP 的问题,而不是你的问题)。
    【解决方案3】:

    这必须至少有两个操作(可能是 3 个)。

    1. 评估z == 3
    2. 分配给x
    3. (可能)评估y + y

    我能想到的最有效的写法是使用三元表达式。

    x = (z == 3) ? y + y : y;
    

    【讨论】:

    • 我以前见过这样的三元表达式——我不明白为什么它们不会产生分支? (我认为它们只是 IF-ELSE 语句的语法糖)。
    • 三元表达式实际上并没有给出相同的结果——当z==3 为假时,OP 的表达式将x 设置为零,但你的不会改变x
    • 视情况而定,但您的三元可能不会导致分支stackoverflow.com/questions/7127759/branch-on-operator
    • @DrewMcGowen 你说得对,我编辑了三元表达式。
    • 哦,我刚刚编辑了我的 Q,因为你让我意识到了一些事情,但不要担心,谢谢你的回答。
    【解决方案4】:

    简单的方法

    x = (z == 3) ? y : x;
    

    复杂的方式

    x = y & (-(z == 3)); // Based on -1 = 1111...11 binary
    

    【讨论】:

      猜你喜欢
      • 2011-12-28
      • 2017-01-12
      • 2020-12-14
      • 1970-01-01
      • 2016-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多