慢速异或操作符
Slow XOR operator
本文关键字:操作符 更新时间:2023-10-16
编辑:事实上,我在计时代码中有一个奇怪的错误导致了这些结果。当我修复了我的错误后,智能版本的运行速度比预期的要快。我的计时代码是这样的:
bool x = false;
before = now();
for (int i=0; i<N; ++i) {
x ^= smart_xor(A[i],B[i]);
}
after = now();
我已经做了^=
来阻止我的编译器优化for循环。但我认为^=
与两个xor函数的相互作用很奇怪。我修改了计时代码,简单地填入一个xor结果数组,然后在计时代码之外使用该数组进行计算。这就解决了问题。
我应该删掉这个问题吗?
结束编辑
我定义了两个c++函数如下:bool smart_xor(bool a, bool b) {
return a^b;
}
bool dumb_xor(bool a, bool b) {
return a?!b:b;
}
我的计时测试表明dumb_xor()
稍微快一些(内联时1.31ns vs 1.90ns,未内联时1.92ns vs 2.21ns)。这使我感到困惑,因为^
操作员应该是一台机器操作。我想知道是否有人有一个解释。
程序集看起来像这样(未内联时):
.file "xor.cpp"
.text
.p2align 4,,15
.globl _Z9smart_xorbb
.type _Z9smart_xorbb, @function
_Z9smart_xorbb:
.LFB0:
.cfi_startproc
.cfi_personality 0x3,__gxx_personality_v0
movl %esi, %eax
xorl %edi, %eax
ret
.cfi_endproc
.LFE0:
.size _Z9smart_xorbb, .-_Z9smart_xorbb
.p2align 4,,15
.globl _Z8dumb_xorbb
.type _Z8dumb_xorbb, @function
_Z8dumb_xorbb:
.LFB1:
.cfi_startproc
.cfi_personality 0x3,__gxx_personality_v0
movl %esi, %edx
movl %esi, %eax
xorl $1, %edx
testb %dil, %dil
cmovne %edx, %eax
ret
.cfi_endproc
.LFE1:
.size _Z8dumb_xorbb, .-_Z8dumb_xorbb
.ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
.section .note.GNU-stack,"",@progbits
我在Intel Xeon X5570上使用g++ 4.4.3-4ubuntu5。
我认为你没有正确地对代码进行基准测试。
我们可以在生成的程序集中看到smart_xor
函数是:
movl %esi, %eax
xorl %edi, %eax
而您的dumb_xor
函数是:
movl %esi, %edx
movl %esi, %eax
xorl $1, %edx
testb %dil, %dil
cmovne %edx, %eax
显然,第一个会更快。
如果没有,那么您就有基准测试问题。
所以你可能想要调整你的基准测试代码…请记住,您需要运行大量电话才能获得良好且有意义的平均值。
考虑到您的"愚蠢的异或"代码明显更长(并且大多数指令依赖于前一个指令,因此它不会并行运行),我怀疑您的结果中存在某种测量误差。
编译器将需要为"智能异或"的脱线版本生成两条指令,因为数据输入的寄存器不是给出返回结果的寄存器,因此数据必须从EDI和ESI移动到EAX。在内联版本中,代码应该能够在调用之前使用数据所在的任何寄存器,如果代码允许,结果将保留在它进入的寄存器中。
调用脱行函数的执行时间可能至少与函数中的实际代码一样长。
如果您显示您用于基准测试的测试工具也会有所帮助…
相关文章:
- 为什么map有操作符[],set没有
- 我可以将C 17 Capture lambda ConstexPR转换操作符的结果用作函数指针模板非类型参数吗?
- c++新操作符通过libstdc++占用大量内存(67MB)
- 复制/移动操作符是否可以安全地用于实现复制/移动分配操作符
- 提升::精神::因果报应使用有条件的替代操作符(|)
- 促进几何体操作符
- 如果操作符delete没有实现,为什么不编译它
- 在使用放置新操作符时,我真的需要担心对齐问题吗
- 我怎样才能让getline操作符工作
- 在重载的全局new操作符中使用静态对象会导致核心转储运行时错误
- 提升ipc new和delete操作符
- 在c++中使用new操作符动态分配数组
- 操作符的大小在C++
- 如何将向量中的对象传递给操作符
- 一个更容易的拷贝分配操作符实现
- 如何重写复杂的c++代码行(嵌套的三元操作符)
- boost::make_shared没有调用(放置)操作符new
- 新操作符(以及malloc)无法分配~450MB的内存
- 类、异常和操作符
- 当delete操作符释放内存时,我为什么需要析构函数