6.5 示例

下面的程序用于测试不同优化等级的优化效果:

include

double

powern (double d, unsigned n)

{

double x = 1.0;

unsigned j;

for (j = 1; j <= n; j++)

x *= d;

return x;

}

int

main (void)

{

double sum = 0.0;

unsigned i;

for (i = 1; i <= 100000000; i++)

{

sum += powern (i, i % 5);

}

printf ("sum = %g\n", sum);

return 0;

}

这个主函数包含一个调用powern函数的循环。这个函数通过连续乘法计算一个浮点数的n次幂。之所以选择这个程序是因为它同时适合函数内联和循环展开。在GNU Bash shell中运行时的程序可以使用time命令测试程序运行时间。

这是上面程序的测试结果,在566MHz的Intel Celeron带有16KB的一级缓存和128KB的二级缓存的处理器上编译,编译环境GCC 3.3.1,GNU/Linux:

$ gcc -Wall -O0 test.c -lm

$ time ./a.out

real 0m13.388s

user 0m13.370s

sys 0m0.010s

$ gcc -Wall -O1 test.c -lm

$ time ./a.out

real 0m10.030s

user 0m10.030s

sys 0m0.000s

$ gcc -Wall -O2 test.c -lm

$ time ./a.out

real 0m8.388s

user 0m8.380s

sys 0m0.000s

$ gcc -Wall -O3 test.c -lm

$ time ./a.out

real 0m6.742s

user 0m6.730s

sys 0m0.000s

$ gcc -Wall -O3 -funroll-loops test.c -lm

$ time ./a.out

real 0m5.412s

user 0m5.390s

sys 0m0.000s

测试结果中的’user’条目是程序真正的运行时间,它给出的是CPU运行此程序所花费的实际时间。其他条目’real’和’sys’记录了程序总共运行的时间(包括其他程序使用的CPU时间)和等待操作系统调用所花费的时间。即使上面的测试都只运行一个程序,测试结果都是经过了多次运行之后得出来的。

从结果中我们可以看出优化等级越高编译出来的程序运行速度越快。’-funroll-loops’选项生成了一个运行更快的可执行文件。最高等级的优化比没有优化的程序执行速度快两倍多。

注意像上面这样的小程序需要考虑操作系统和编译器版本之间的差异。例如在一个2.0GHz的Intel 奔腾CPU 4M系统中使用相同版本的GCC编译程序’-O2’会比’-O1’选项生成的程序执行速度稍慢一点。它说明了一个重要的观点:优化不可能在任何情况下都使程序运行速度更快。