C++ 条件上的按位操作设置变量
在C/C++应用程序中,我有三个变量——x、y和z。当z=3时,我想设置x=y。我可以使用乘法来实现这一点:C++ 条件上的按位操作设置变量,c++,c,performance,optimization,bit-manipulation,C++,C,Performance,Optimization,Bit Manipulation,在C/C++应用程序中,我有三个变量——x、y和z。当z=3时,我想设置x=y。我可以使用乘法来实现这一点: x = y * (z == 3) 但这是在一个大循环中调用的,IMUL将占用4个CPU周期。我希望能找到一个需要1个CPU周期的位操作 编辑:编译器MSVC 64位编译、平台Win 7 64、x86体系结构、Ivy Bridge或Haswell。这必须是至少两个操作(可能是3个) 评估z==3 分配给x (可能)评估y+y 我能想到的写它的最有效的方法是使用三元表达式 x = (z =
x = y * (z == 3)
但这是在一个大循环中调用的,IMUL将占用4个CPU周期。我希望能找到一个需要1个CPU周期的位操作
编辑:编译器MSVC 64位编译、平台Win 7 64、x86体系结构、Ivy Bridge或Haswell。这必须是至少两个操作(可能是3个)
z==3
x
y+y
x = (z == 3) ? y + y : y;
这必须是至少两个操作(可能是3个)
z==3
x
y+y
x = (z == 3) ? y + y : y;
写:
(或其他任何你编辑你的问题到下一个)并激活你的编译器。这就是编译器的用途。你可以用编译器开关说出你想要的,编译器会比你做得更好 写:
if ( z == 3 )
x = y * 2;
else
x = y;
(或其他任何你编辑你的问题到下一个)并激活你的编译器。这就是编译器的用途。你可以用编译器开关说出你想要的,编译器会比你做得更好 在二的补码上,表达式:
(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()
:
对于foo2()
,还有一条指令(尽管可能更便宜):
但是,对于foo3()
,您可以得到:
xorl %eax, %eax
cmpl $3, 8(%esp)
cmove 4(%esp), %eax
尽管它是一条条件移动指令,但代码并没有比这更紧凑。在二的补码中,表达式:
(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()
:
对于foo2()
,还有一条指令(尽管可能更便宜):
但是,对于foo3()
,您可以得到:
xorl %eax, %eax
cmpl $3, 8(%esp)
cmove 4(%esp), %eax
尽管这是一条有条件的移动指令,但代码并没有变得比这更紧凑。简易方法
x = (z == 3) ? y : x;
复杂方式
x = y & (-(z == 3)); // Based on -1 = 1111...11 binary
捷径
x = (z == 3) ? y : x;
复杂方式
x = y & (-(z == 3)); // Based on -1 = 1111...11 binary
你说的是“将采取”而不是“确实采取”。您是否查看了生成的程序集以进行确认?
z==3
将解析为布尔值,因此它将是0或1,因此结果将是y或0。根据平台的不同,条件可能更好。例如,大多数ARM指令都是有条件的,编译器可以利用这一点。此外,就像前面提到的@ddriver一样,如果z
不是3,那么x
将设置为0。这是您想要的吗?您指定的体系结构上的整数ALU操作应该需要1个单周期。-第60页你说的是“将采取”而不是“确实采取”。您是否查看了生成的程序集以进行确认?z==3
将解析为布尔值,因此它将是0或1,因此结果将是y或0。根据平台的不同,条件可能更好。例如,大多数ARM指令都是有条件的,编译器可以利用这一点。此外,就像前面提到的@ddriver一样,如果z
不是3,那么x
将设置为0。这是您想要的吗?您指定的体系结构上的整数ALU操作应该需要1个单周期。-第60页我以前见过在这样的事情中使用三元表达式-我不明白为什么它们不引起分支?(我还以为它们只是IF-ELSE语句的语法糖。)三元表达式实际上不会给出相同的结果-当z==3
为false时,OP的表达式将x
设置为零,但你的表达式不会改变x
,这取决于情况,但很可能你的三元表达式不会导致@DrewMcGowen分支,如果你是正确的,我编辑了三元表达式。哦,我刚刚编辑了我的Q,因为你让我意识到了一些事情,但是不要担心,谢谢你的回答。我以前见过三元表达式在这样的事情中使用过——我不明白为什么它们不引起分支?(我还以为它们只是IF-ELSE语句的语法糖。)三元表达式实际上不会给出相同的结果-当z==3
为false时,OP的表达式将x
设置为零,但你的表达式不会改变x
,这取决于情况,但很可能你的三元表达式不会导致@DrewMcGowen分支,如果你是正确的,我编辑了三元表达式。哦,我只是编辑了我的Q,因为你让我意识到了一些事情,但不用担心,谢谢你的回答。是的,但它将x
设置为y
或2y
,这与问题本身形成对比(当然,这是OP的问题,不是你的)。是的,但它将x
设置为y
或2y
,这与问题本身形成对比(当然,这是OP的问题,不是你的问题)。