M. *_*its 8 c++ performance assembly bit-shift
我意识到答案可能是硬件特定的,但我很好奇是否有一种更普遍的直觉,我错过了?
我问了这个问题并给出了答案,现在我想知道我是否应该改变我的方法一般使用"(i << 1 | 1)"而不是"(2*i + 1)"??
pax*_*blo 13
由于ISO标准实际上并未要求性能要求,这将取决于实现,所选的编译器标志,目标CPU以及很可能是月亮的相位.
这些优化(节省几个周期)在投资回报方面几乎总是微不足道,而不是像算法选择这样的宏观优化.
首先瞄准代码的可读性.如果您的意图是移位,并OR使用位移版本.如果您的意图是倍增,请使用该*版本.一旦确定存在问题,只关心性能.
任何体面的编译器都会比你能更好地优化它:-)
只是关于"......它将使用LEA"的答案的实验:
以下代码:
int main(int argc, char **argv)
{
#ifdef USE_SHIFTOR
return (argc << 1 | 1);
#else
return (2 * argc + 1);
#endif
}
Run Code Online (Sandbox Code Playgroud)
将gcc -fomit-frame-pointer -O8 -m{32|64}(用于32位或64位)编译成以下汇编代码:
080483a0 <main>: 80483a0: 8b 44 24 04 mov 0x4(%esp),%eax 80483a4: 8d 44 00 01 lea 0x1(%eax,%eax,1),%eax 80483a8: c3 ret
00000000004004c0 <main>: 4004c0: 8d 44 3f 01 lea 0x1(%rdi,%rdi,1),%eax 4004c4: c3 retq
-DUSE_SHIFTOR:080483a0 <main>: 80483a0: 8b 44 24 04 mov 0x4(%esp),%eax 80483a4: 01 c0 add %eax,%eax 80483a6: 83 c8 01 or $0x1,%eax 80483a9: c3 ret
-DUSE_SHIFTOR:00000000004004c0 <main>: 4004c0: 8d 04 3f lea (%rdi,%rdi,1),%eax 4004c3: 83 c8 01 or $0x1,%eax 4004c6: c3 retq
事实上,大多数情况都会使用LEA.然而,这两个案例的代码并不相同.这有两个原因:
<<或|不能(x + 1) == (x | 1)只有!(x & 1)在添加到下一位的情况下才有效.通常,仅添加一个导致在一半的情况下设置最低位.虽然我们(和编译器,可能)知道第二个必然适用,但第一个仍然是可能的.因此,编译器会创建不同的代码,因为"或 - 版本"需要将位0强制为1.
除了脑力不足的编译器之外,任何人都会看到这些表达式是等效的,并将它们编译为相同的可执行代码.
通常情况下,优化像这样的简单算术表达式并不值得过多担心,因为它是编译器最擅长优化的东西.(与"智能编译器"可以做正确的事情的许多其他情况不同,但是实际的编译器会失败.)
这将通过PPC,Sparc和MIPS上的相同指令顺序进行:顺序后跟添加.在ARM上,它将煮熟为单个融合的移位添加指令,而在x86上,它可能是单个LEA操作.
| 归档时间: |
|
| 查看次数: |
815 次 |
| 最近记录: |