Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/git/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance x86 inc与add指令的相对性能_Performance_Assembly_Optimization_X86_Increment - Fatal编程技术网

Performance x86 inc与add指令的相对性能

Performance x86 inc与add指令的相对性能,performance,assembly,optimization,x86,increment,Performance,Assembly,Optimization,X86,Increment,快速提问,事先假设 mov eax, 0 哪个更有效 inc eax inc eax 或 此外,如果两个incs速度更快,编译器(比如GCC)是否通常(即不带积极优化标志)对其进行var+=2优化 PS:不要费心回答“不要过早优化”,这仅仅是学术兴趣。就所有目的而言,这可能并不重要。但要考虑到inc使用的字节更少 考虑以下代码: int x = 0; x += 2; 不使用任何优化标志,GCC将此代码编译为: 80483ed: c7 44 24 1c 00 00 00 m

快速提问,事先假设

mov eax, 0
哪个更有效

inc eax
inc eax

此外,如果两个
inc
s速度更快,编译器(比如GCC)是否通常(即不带积极优化标志)对其进行
var+=2
优化


PS:不要费心回答“不要过早优化”,这仅仅是学术兴趣。

就所有目的而言,这可能并不重要。但要考虑到inc使用的字节更少

考虑以下代码:

int x = 0;
x += 2;
不使用任何优化标志,GCC将此代码编译为:

80483ed:       c7 44 24 1c 00 00 00    movl   $0x0,0x1c(%esp)
80483f4:       00 
80483f5:       83 44 24 1c 02          addl   $0x2,0x1c(%esp)
使用
-O1
-O2
,它变为:

c7 44 24 08 02 00 00    movl   $0x2,0x8(%esp)
有趣的是,不是吗?

如果您想知道x86指令的原始性能统计,请参阅(确切地说是第4卷)。至于关于编译器的部分,这取决于编译器的代码生成器,而不是你应该依赖太多的东西


另一方面:我觉得有趣/讽刺的是,在一个关于性能的问题中,你使用
MOV-EAX,0
将寄存器归零,而不是
XOR-EAX,EAX
:p(如果
MOV-EAX,0
是事先做的,最快的变化就是删除inc和add,而只是
MOV-EAX,2
).

同一寄存器上的两条
inc
指令(或者更一般地说,两条读-修改-写指令)始终具有至少两个周期的依赖链。这是假设inc的延迟为一个时钟,这是自486以来的情况。这意味着,如果周围的指令不能与两条inc指令交错以隐藏这些延迟,代码将执行得较慢

但无论如何,没有编译器会发出您建议的指令序列(
mov-eax,0
将被
xor-eax,eax
,请参阅)

它将被优化为

mov eax,2

从《英特尔手册》中,您可以发现,在一种特定的体系结构上,ADD/SUB指令的成本似乎要低半个周期。但请记住,英特尔(最近)的处理器采用无序执行模式。这主要意味着,性能瓶颈在处理器必须等待数据进入的任何地方都会出现(例如,在L1/L2/L3/RAM数据获取过程中,处理器没有事情可做)。所以,如果你是探查器告诉你,公司可能是问题所在;从数据吞吐量的角度看它,而不是看原始周期计数

Instruction              Latency1           Throughput         Execution Unit 
                                                            2 
CPUID                    0F_3H    0F_2H      0F_3H    0F_2H    0F_2H 

ADD/SUB                  1        0.5        0.5      0.5      ALU 
[...]
DEC/INC                  1        1          0.5      0.5      ALU 

答案可能是处理器特定的,在大多数情况下,很可能没有可测量的差异。如果你真的有兴趣知道一个特定CPU的答案,那么就对它进行基准测试。IIRC 0f_2h的可能复制品是P4 Prescott,愿他安息。这些半时钟延迟是由内部双时钟管道造成的。这对英特尔来说是一个非常糟糕的主意;不过,大多数编译器都喜欢inc-eax而不是
mov-eax,1
。可能是因为它是3字节而不是5。@LưuVĩnhPhúc
mov eax,1
是5字节:
b8 01 00
。由于8字节的文字和QWORD前缀:
48 b8 01 00 00
,64位为10字节。相对而言,
xor-rax,rax;inc-eax只有5个字节:
48 31 c0 ff c0
@多项式:所有现代主流编译器都将使用
mov-eax,1
,除非您特别告诉他们优化大小而不是速度(-clang或ICC
-Os-m32
或MSVC
-O1
将在32位模式下使用
xor
/
inc
gcc-Os-m32
仍使用mov)。在优化速度时,为后端节省2字节的代码大小并不值得额外的uop(或为前端额外的解码指令).clang
-Oz
要在不考虑速度的情况下优化大小,将在64位模式下使用
push 1
/
pop rax
。所有这些编译器都使用
mov
和正常选项。@phuclv:您可能应该清理您以前的注释;早期的注释中有几个错误(也是在Polynomy的第2条注释中,64位字节计数膨胀)。选项包括
mov-eax,1
(5字节)通过隐式零扩展设置RAX=1,或
push 1
/
(3字节),或
xor-eax,eax
/
inc-eax
(4字节)。但编译器只使用
mov
,除非优化大小超过速度。指出,从另一个已知值的寄存器中选择3字节
leaeax、[rdx+1]
可能很有用
mov eax,2
Instruction              Latency1           Throughput         Execution Unit 
                                                            2 
CPUID                    0F_3H    0F_2H      0F_3H    0F_2H    0F_2H 

ADD/SUB                  1        0.5        0.5      0.5      ALU 
[...]
DEC/INC                  1        1          0.5      0.5      ALU