前几天我遇到了一个使用GCC和'-Ofast'优化标志的奇怪问题.使用'gcc -Ofast -o fib1 fib1.c'编译以下程序.
#include <stdio.h>
int f1(int n) {
if (n < 2) {
return n;
}
int a, b;
a = f1(n - 1);
b = f1(n - 2);
return a + b;
}
int main(){
printf("%d", f1(40));
}
Run Code Online (Sandbox Code Playgroud)
在测量执行时间时,结果是:
peter@host ~ $ time ./fib1
102334155
real 0m0.511s
user 0m0.510s
sys 0m0.000s
Run Code Online (Sandbox Code Playgroud)
现在让我们在程序中引入一个全局变量,然后使用'gcc -Ofast -o fib2 fib2.c'再次编译.
#include <stdio.h>
int global;
int f1(int n) {
if (n < 2) {
return n;
}
int a, b;
a = f1(n - 1);
b = f1(n - 2);
global = 0;
return a + b;
}
int main(){
printf("%d", f1(40));
}
Run Code Online (Sandbox Code Playgroud)
现在执行时间是:
peter@host ~ $ time ./fib2
102334155
real 0m0.265s
user 0m0.265s
sys 0m0.000s
Run Code Online (Sandbox Code Playgroud)
新的全局变量没有任何意义.但是,执行时间的差异很大.
除了问题(1)这种行为的原因是什么,如果(2)在不引入无意义的变量的情况下可以实现最后的表现,那也是很好的.有什么建议?
谢谢彼得
在我的机器上 ( gcc (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010) 我有这个:
time ./fib1 0,36s user 0,00s system 98% cpu 0,364 total
time ./fib2 0,20s user 0,00s system 98% cpu 0,208 total
从man gcc:
-Ofast
无视严格的标准合规性。-Ofast 启用所有 -O3 优化。它还可以实现并非对所有符合标准的程序都有效的优化。它打开 -ffast-math 以及 Fortran 特定的 -fno-protect-parens 和 -fstack-arrays。
不太安全的选择,让我们尝试一下-O2:
time ./fib1 0,38s user 0,00s system 99% cpu 0,377 total
time ./fib2 0,47s user 0,00s system 99% cpu 0,470 total
我认为,一些激进的优化并未应用于fib1,而是应用于fib2. 当我切换-Ofast为-O2- 时,一些优化并未应用于fib2,而是应用于fib1.
咱们试试吧-O0:
time ./fib1 0,81s user 0,00s system 99% cpu 0,812 total
time ./fib2 0,81s user 0,00s system 99% cpu 0,814 total
未经优化,它们是相等的。
因此,在递归函数中引入全局变量,一方面可以破坏某些优化,另一方面可以改善其他优化。