位算子,而不是在分支中使用XOR
Bitwise operators, not vs xor use in branching
在问这个问题之后,我收到了 @andonm.coleman的一条非常有趣的评论,我必须验证。
由于您的拆卸代码是为X86编写的,因此值得指出的是,XOR会设置/清除零标志,而不会(如果您想在不影响依赖于从中依靠标志的跳跃条件的位置操作)执行位置操作的情况下,则没有用以前的操作)。现在,考虑到您不是直接编写组件,您确实无法以有意义的方式访问此标志,所以我怀疑这是一个偏爱另一个标志的原因。
他的评论让我好奇以下代码是否会产生相同的大会说明
#include <iostream>
int main()
{
unsigned int val = 0;
std::cout << "Enter a numeric value: ";
std::cin >> val;
if ( (val ^ ~0U) == 0)
{
std::cout << "Value inverted is zero" << std::endl;
} else
{
std::cout << "Value inverted is not zero" << std::endl;
}
if ( (~val) == 0)
{
std::cout << "Value inverted is zero" << std::endl;
} else
{
std::cout << "Value inverted is not zero" << std::endl;
}
return 0;
}
以下两个操作
if ( (val ^ ~0U) == 0 )
和
if ( (~val) == 0 )
未在Visual Studio 2010中进行优化提供以下拆卸:
if ( (val ^ ~0U) == 0)
00AD1501 mov eax,dword ptr [val]
00AD1504 xor eax,0FFFFFFFFh
00AD1507 jne main+86h (0AD1536h)
if ( (~val) == 0)
00AD1561 mov eax,dword ptr [val]
00AD1564 not eax
00AD1566 test eax,eax
00AD1568 jne main+0E7h (0AD1597h)
我的问题涉及优化。写
更好if ( (val ^ ~0U) == 0)
或
if ( (~val) == 0)
这取决于很多事情,但主要是(如果有的话),请告诉编译器以优化。
如果将编译器设置为优化大小(最小的字节码),则有时会在看似奇怪的地方使用XOR
。例如,可变长度编码方案x86使用可以通过 XOR
'以少于MOV
指令所需的代码字节来将寄存器设置为 0 。
考虑使用XOR
:
的代码 if ( (val ^ ~0U) == 0 ) /* 3-bytes to negate and test (x86) */
&nbsp;&nbsp;&nbsp;&nbsp; XOR eax,0FFFFFFFFh
需要3个bytes 和 sets/sets/clear零标志(zf)
现在,考虑使用NOT
的代码:
if ( (~val) == 0) /* 4-bytes to negate and test (x86) */
&nbsp;&nbsp;&nbsp;&nbsp;NOT eax
编码为2字节说明,但不影响CPU标志。
&nbsp;&nbsp;&nbsp;&nbsp;TEST eax,eax
添加了额外的2个字节,并且需要设置/清除零标志(ZF)
NOT
也是一个简单的指令,但是由于它不会影响任何CPU标志,因此您必须在代码中看到的TEST
指令以将其用于分支。这实际上会产生较大的字体模式,因此可以优化大小的智能编译器可能会可能尝试避免使用NOT
。在CPU生成之间,这两个指令共同完成了多少个周期,而智能编译器也会将其纳入其决策中以优化速度。
如果您不编写手工调整的组件,最好使用对人类最清晰的任何内容,并希望编译器足够聪明,可以选择不同的说明/调度/调度。根据需要在编译时优化尺寸/速度。编译器具有用于选择和安排说明的智能启发式方法,他们对目标CPU架构的了解更多,而不是普通编码器。
稍后您发现该分支确实是一个瓶颈,并且在问题上没有更高级别的方法,那么您可以进行一些低级调整。但是,除非您针对低功率嵌入式CPU或内存有限的设备之类的东西,否则这几天要专注于这些天是如此微不足道的事情。我曾经曾经通过手动调整挤出足够的表现,以使其值得,这是在算法中受益于数据并行性的算法,并且编译器不够聪明,无法有效利用MMX/SSE等专业指导集。
<</p> <</p> <</p>- 我的神经网络不起作用 [XOR 问题]
- IPC使用多个管道和分支进程来运行Python程序
- 如何删除peer if else分支中的冗长句子
- 如何确保在使用基于布尔值的两个方法之一调用方法时避免分支预测错误
- 如何正确地将分支添加到已存在的树中
- 如何将分支添加到已存在的TTree:ROOT
- 使用模板化运算符重载 XOR 运算符失败
- 如何删除 LLVM 中的不规则分支?
- 使用XOR查找O(n)-解决方案中的两个字符串是否为变位符
- Cuda:具有位集数组的 XOR 单位集
- 如果以下行不包含决策或分支,GDB 无法单步跳过函数
- 函数指针与条件分支
- 分支未在 Linux 上采用
- 如何删除分支因子不一致的树,最大为 30,40
- std::shared_ptr vs std::make_shared:意外的缓存未命中和分支预测
- 如何通过使用 2 位或更多数字的 XOR 运算符来执行此操作C++问题
- 更改 git 分支名称后,在项目的 Visual Studio 代码中丢失智能感知(建议,转到定义C++
- 使用 XOR 逻辑查找缺失的数字
- 条件分支评估
- 位算子,而不是在分支中使用XOR