关于编译器 (GCC) 所做的优化,标准做法是什么?每个选项(-O、-O1、-O2、-O3、-Os、-s、-fexpensive-optimizations)有什么不同,我如何决定什么是最佳的?
2 回答
通常 -O2 是一个很好的优化级别,可以先尝试。
但是,如果您想要尽可能好的结果,您最终会尝试许多优化级别,因为您无法事先判断哪个级别最适合您的应用程序。
另请注意,优化结果应因每个 CPU 而异(在某些优化大小的 CPU 实际上可能比优化速度产生更好的速度)。
仅供将来参考,这里是每个级别的简要说明(您可以在文档http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html中找到完整说明):
-O(与 -O1 相同):使用 -O,编译器会尝试减少代码大小和执行时间,而不执行任何需要大量编译时间的优化。
-O2:进一步优化。GCC 执行几乎所有支持的优化,不涉及空间速度折衷。与 -O 相比,此选项增加了编译时间和生成代码的性能。
-O3:进一步优化。-O3 打开 -O2 指定的所有优化,同时打开 -finline-functions、-funswitch-loops、-fpredictive-commoning、-fgcse-after-reload、-ftree-vectorize、-ftree-partial-pre 和 - fipa-cp-克隆选项。
-Os:优化大小。-Os 启用通常不会增加代码大小的所有 -O2 优化。它还执行旨在减少代码大小的进一步优化。
-Ofast:无视严格的标准合规性。-Ofast 启用所有 -O3 优化。它还支持并非对所有符合标准的程序都有效的优化。它打开 -ffast-math 以及 Fortran 特定的 -fno-protect-parens 和 -fstack-arrays。如果您使用多个 -O 选项,无论有无级别编号,最后一个这样的选项是有效的。
Linux 内核Makefile
同时提供-O2
和-Os
. 如果缺少进一步的细节,任何一个都是合适的。
-Os
针对小型存储进行了优化。由于如今 CPU 的速度明显快于主内存,因此即使在大型机器上优化小型存储也是有意义的——任何等待从主内存填充高速缓存的时间都是浪费时间。因此,通过编译来最大限度地利用指令缓存以提高空间效率,也许执行时间也会有所改善。
运行所有“通常的-O2
优化”,并且选择的优化将是安全的。(我听说有些-O3
优化并不总是安全的,但这可能是因为 Linux 内核运行时会受到一些通常应用程序不常见的约束。)
当然,最好的答案是用多级优化编译你的软件;time 编译软件需要多长时间,以及软件通过代表性基准测试需要多长时间。测量它们全部使用了多少内存。
然后选择编译速度、运行时速度和运行时内存使用的“最佳”组合。您可能想要最快的编译速度,或者您可能想要最快的运行时间,或者您可能正在尝试从虚拟主机提供商处安装更少量的内存以节省资金。
-O2
不做任何测量就直接挑选可能是公平的。