首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >慢异或运算符

慢异或运算符
EN

Stack Overflow用户
提问于 2013-04-27 00:56:10
回答 2查看 628关注 0票数 6

编辑:事实上,我的计时代码中有一个奇怪的错误导致了这些结果。当我修复我的错误时,智能版本的速度就像预期的那样快。我的计时代码如下所示:

代码语言:javascript
复制
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++函数,如下所示:

代码语言:javascript
复制
bool smart_xor(bool a, bool b) {
  return a^b;
}

bool dumb_xor(bool a, bool b) {
  return a?!b:b;
}

我的计时测试表明,dumb_xor()的速度稍快一些(内联时为1.31 vs,非内联时为1.92 vs,2.21 vs)。这让我感到困惑,因为^操作符应该是单机操作。我想知道有没有人能解释一下。

程序集看起来像这样(当不是内联时):

代码语言:javascript
复制
    .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

我在英特尔至强X5570上使用g++ 4.4.3-4ubuntu5。我是用-O3编译的。

EN

回答 2

Stack Overflow用户

发布于 2013-04-27 01:06:15

我不认为您对代码进行了正确的基准测试。

我们可以在生成的程序集中看到您的smart_xor函数是:

代码语言:javascript
复制
movl    %esi, %eax
xorl    %edi, %eax

而你的dumb_xor函数是:

代码语言:javascript
复制
movl    %esi, %edx
movl    %esi, %eax
xorl    $1, %edx
testb   %dil, %dil
cmovne  %edx, %eax

所以很明显,第一个会更快。

如果没有,那么您就会遇到基准测试问题。

所以你可能想要调优你的基准测试代码...记住,你需要运行大量的调用才能得到一个好的和有意义的平均值。

票数 5
EN

Stack Overflow用户

发布于 2013-04-27 01:03:59

鉴于您的“哑异或”代码要长得多(而且大多数指令都依赖于前一条指令,因此它不会并行运行),我怀疑您的结果中存在某种度量错误。

编译器将需要为“智能XOR”的离线版本生成两条指令,因为数据传入的寄存器不是返回结果的寄存器,因此数据必须从EDI和ESI移动到EAX。在内联版本中,代码应该能够在调用之前使用数据所在的任何寄存器,如果代码允许,结果将保留在它作为寄存器的位置。

调用函数是越行的,其执行时间可能至少与函数中的实际代码一样长。

如果你也展示你用于基准测试的测试工具,那会很有帮助……

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16241544

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档