arm*_*ues 4 c++ optimization performance stack static
我试图了解全局静态变量的性能,并遇到了一个非常奇怪的场景。下面的代码平均需要大约 525 毫秒。
static unsigned long long s_Data = 1;
int main()
{
unsigned long long x = 0;
for (int i = 0; i < 1'000'000'000; i++)
{
x += i + s_Data;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
下面的代码平均需要 1050 毫秒。
static unsigned long long s_Data = 1;
int main()
{
unsigned long long x = 0;
for (int i = 0; i < 1'000'000'000; i++)
{
x += i;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我知道访问静态变量很快,根据我的其他测试,写入它们很慢,但我不确定在上述场景中我错过了哪些信息。注意:编译器优化已关闭,并使用 MSVC 编译器来执行测试。
小智 8
为了解决实际问题,在关闭优化的情况下,我们可以转向生成的程序集来了解为什么一个程序集比另一个程序集运行得更快。
在第一个测试中,GCC(主干)https://godbolt.org/z/GdssT9vME生成此程序集
s_Data:
.quad 1
main:
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], 0
mov DWORD PTR [rbp-12], 0
jmp .L2
.L3:
mov eax, DWORD PTR [rbp-12]
movsx rdx, eax
mov rax, QWORD PTR s_Data[rip]
add rax, rdx
add QWORD PTR [rbp-8], rax
add DWORD PTR [rbp-12], 1
.L2:
cmp DWORD PTR [rbp-12], 999999999
jle .L3
mov eax, 0
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
第二个测试https://godbolt.org/z/5ndnEv5Ts我们得到
main:
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], 0
mov DWORD PTR [rbp-12], 0
jmp .L2
.L3:
mov eax, DWORD PTR [rbp-12]
cdqe
add QWORD PTR [rbp-8], rax
add DWORD PTR [rbp-12], 1
.L2:
cmp DWORD PTR [rbp-12], 999999999
jle .L3
mov eax, 0
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
比较这两个程序,第一个程序有十六条指令,而第二个程序只有十四条指令。(我相信你可以猜到不同的指令也有不同的CPU周期开销)
每条汇编指令需要多少个CPU周期?
正如我的评论中所指出的,优化极大地改变了生成的程序集。
两个测试都会产生这个-O2
main:
xor eax, eax
ret
Run Code Online (Sandbox Code Playgroud)