gcc优化级别之间有什么区别?
GCC中不同优化级别之间有何区别?假设我不在乎是否有任何调试挂钩,为什么我不只使用可用的最高级别的优化呢?更高级别的优化是否必然(即证明是)会生成更快的程序?
解决方案
通常,优化级别高于-O2(对于gcc仅为-O3,但其他编译器具有更高的优化级别)包括可以增加代码大小的优化。这包括诸如循环展开,大量内联,不考虑大小而对齐的填充等操作。其他编译器提供矢量化和跨过程的优化,其级别高于-O3,并且某些优化可以大大提高速度。正确性的代价(例如,使用更快,更不准确的数学例程)。使用这些东西之前,请先检查文档。
至于性能,这是一个权衡。通常,编译器设计师会尝试调整这些内容,以免降低代码的性能,因此-O3通常会有所帮助(至少以我的经验而言),但是努力可能会有所不同。并非总是如此,真正积极的尺寸更改优化会提高性能(例如,真正积极的内联可让我们缓存污染)。
我找到了一个网页,其中包含有关不同优化级别的一些信息。记得在某处听到的一件事是,优化实际上可能会破坏程序,这可能是一个问题。但是我不确定一个问题会持续多久。也许当今的编译器足够聪明,可以解决这些问题。
是的,更高的级别有时可能意味着程序性能更好。但是,它可能会导致问题,具体取决于代码。例如,分支预测(在-O1及更高版本中启用)可以通过引起竞争条件来破坏编写不佳的多线程程序。优化实际上会决定比我们编写的要好的东西,在某些情况下可能不起作用。
有时,较高的优化(-O3)不会带来任何合理的好处,但会带来很多额外的规模。我们自己的测试可以确定这种大小折衷是否可以为系统带来合理的性能提升。
最后要注意的是,GNU项目默认情况下在-O2编译所有程序,而-O2在其他地方相当普遍。
边注:
很难确切预测gcc命令行上针对不同版本和平台的全局`-O'指令打开了哪些标志,并且GCC网站上的所有文档可能很快就会过时或者无法涵盖编译器。内部细节。
当我们使用-O
标志和其他-f
标志之一和/或者它们的组合时,这是一种简单的方法来准确检查在特定设置上会发生什么:
- 在某处创建一个空的源文件:
touch dummy.c
- 尽管编译器可以像平常一样通过它来运行它,并带有通常使用的所有-O,-f和/或者-m标志,但是在命令行中添加了-Q -v gcc -c -Q -v dummy.c`
- 检查生成的输出,也许将其保存以用于不同的运行。
- 根据喜好更改命令行,通过
rm -f dummy.o
删除生成的目标文件,然后重新运行。
另外,请始终牢记,从纯粹的角度来看,大多数非平凡的优化都会生成"断点"代码(断点被定义为在极端情况下偏离最佳路径),因此请选择是否启用特定代码一组优化机制有时归结为选择编译器输出的正确性级别。在任何编译器的优化器中总是存在(现在是)错误,只需检查GCC邮件列表和Bugzilla中的一些示例即可。编译器优化只应在实际执行测量之后使用,因为使用更好的算法获得的收益将使编译器优化的任何收益相形见,。优化代码没有必要在蓝月亮中每一次运行一次,如果优化器引入了错误,则如何进行无关紧要加快代码运行速度。