39

我对 GCC -O3 标志非常熟悉,但它与 -Os 有何不同,在哪种情况下我们应该更喜欢一个?

4

5 回答 5

45

GCC 文档非常明确地描述了这些选项的作用。

-O3 尝试非常优化代码以提高性能。它包括所有优化 -O2 包括,以及更多。

另一方面,-Os 指示 GCC “优化大小”。它启用所有不会增加可执行文件大小的-O2 优化,然后它还切换一些优化标志以进一步减小可执行文件大小。

请注意,我的描述故意含糊不清 - 阅读 GCC 文档以更深入地讨论究竟为任一优化级别启用了哪些标志。

我相信 -O* 优化级别就是——互斥的、不同的优化级别。混合它们并没有真正的意义,因为两个级别将启用或忽略另一个级别有意忽略或启用的标志(分别)。如果你想混合和匹配(你可能实际上不想这样做,除非你有一个非常好的理由想要一组特定的标志),你最好阅读文档并混合和匹配每个级别的标志手动启用。

我想我还将链接来自 Gentoo Linux Wiki 的这篇文章,它讨论了优化标志,因为它们与构建操作系统的包有关。显然,并非所有这些都适用,但它仍然包含一些有趣的信息——例如:

使用 -O3 进行编译并不能保证提高性能,事实上,在许多情况下,由于二进制文件较大和内存使用量增加,可能会降低系统速度。-O3 也可以破坏多个包裹。因此,不建议使用 -O3。

根据那篇文章,在大多数情况下,-O2 与 -O3 一样“好”,并且就损坏的可执行输出而言,使用起来更安全。

于 2013-10-30T16:53:50.980 回答
18

我建议阅读 GCC 文档。-O3用于获得快速运行的代码(即使以一些代码膨胀为代价),同时-Os优化生成代码的大小。

还有大量其他(晦涩的)GCC优化标志(例如-fgcse-sm),其中许多甚至在-O3.

您可能还对-flto(用于Link-Time Optimization)感兴趣,除了 eg -O3or -Os,在编译时和链接时都可以使用。然后也看到这个答案

最后,请注意使用最新版本的 GCC(目前为 2013 年底的 4.8),因为 GCC 正在显着改进其优化。

您可能还想使用-mtune=native(至少对于 x86)。

您甚至可以编写自己的优化通道,特定于您自己的特定库和 API,也许使用MELT插件。

正如CmdrMoozy 回答的那样,您可能更喜欢使用-O2 over -O3(但请注意,最近的 GCC 版本已经改进了很多-O3,因此Gentoo引用 - 推荐-O3和支持的-O2相关性变得不那么相关了。)。

此外,正如这篇 SlashDot-ed Stack 论文(作者 Xi Wang、Nickolai Zeldovich、M. Frans Kaashoek 和 Armando Solar-Lezama)所表明的,许多程序并不完全符合 C 标准,并且在某些有效的优化完成。未定义的行为是一个棘手的主题。

顺便说一句,请注意 using-O3通常会使您的编译时间更长,并且经常(但不总是)带来最多几个百分点的性能-O2,甚至比-O1....(甚至更糟-flto)。这就是很少使用它的原因。

于 2013-10-30T16:54:47.367 回答
10

这取决于。您需要优化速度或尺寸吗?

-O3
优化更多。-O3 打开 -O2 指定的所有优化,同时打开 -finline-functions、-funswitch-loops、-fpredictive-commoning、-fgcse-after-reload、-ftree-loop-vectorize、-ftree-slp-vectorize 、-fvect-cost-model、-ftree-partial-pre 和 -fipa-cp-clone 选项。

-O0
减少编译时间并使调试产生预期的结果。这是默认设置。

-Os
优化大小。-Os 启用通常不会增加代码大小的所有 -O2 优化。它还执行旨在减少代码大小的进一步优化。
-Os 禁用以下优化标志:

-falign-functions -falign-jumps -falign-loops -falign-labels -freorder-blocks -freorder-blocks-and-partition -fprefetch-loop-arrays

http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

实际上,-O是一长串独立优化的简写。如果您不知道自己需要什么,请选择-O3

于 2013-10-30T16:53:05.960 回答
3

-O3 优化速度,而 -Os 优化空间。这意味着 -O3 会给你一个快速的可执行文件,但它可能会相当大,而 -Os 会给你一个较小的可执行文件,但它可能会更慢。

空间和时间效率通常是一种权衡。更快的算法往往会占用更多空间,而就地算法(不增加空间使用的算法)往往效率较低。

通常现代计算机有足够的内存空间,所以 -O3 通常更可取。但是,如果您正在为低内存(例如小型设备)编程,您可能更喜欢 -Os

于 2013-10-30T17:01:37.273 回答
1

这实际上无法回答,一个简单的规则是使用优化关键代码路径的速度,并优化非关键代码路径的大小,例如加载,...

一些编译器可以分两次工作来为您决定,第一次创建具有分析支持的特殊可执行文件,您运行应用程序以收集数据,第二次编译能够根据最佳数据做出决定。它允许去虚拟化,分支预测,......

于 2013-10-30T16:56:27.353 回答