何时为 gcc 使用 -O2 标志?

Posted

技术标签:

【中文标题】何时为 gcc 使用 -O2 标志?【英文标题】:When to use -O2 flag for gcc? 【发布时间】:2009-05-20 11:59:48 【问题描述】:

如果我使用“-O2”标志,性能会提高,但编译时间会变长。

我如何决定是否使用它?

也许 O2 在某些类型的代码(例如数学计算?)中发挥最大的作用,我应该只将它用于项目的那些部分?

编辑:我想强调一个事实,即为我的项目的所有组件设置 -O2 会将总编译时间从 10 分钟更改为 30 分钟。

【问题讨论】:

这不能回答您的问题,但根据 yoru 编辑,听起来您需要更改构建项目的方式。在初始构建之后,它应该只将修改后的源编译为 .o,然后将 .o 文件链接在一起。 预编译的头文件也有助于提高性能。 【参考方案1】:

我建议大多数时候使用 -O2,好处包括:

通常会减小生成代码的大小(与 -O3 不同)。 更多警告(某些警告需要仅在优化期间进行的分析) 通常会显着提高性能(这可能无关紧要)。

如果发布级代码启用优化,最好在整个开发/测试周期启用优化。

启用优化后,源代码级调试更加困难,有时在调试问题时禁用优化会有所帮助。

【讨论】:

如果你需要减少代码大小,为什么不使用-Os而不是-O2? 如果代码大小是最重要的优化因素,则使用 -Os 是有意义的 - 通常不是(小型嵌入式系统除外...) 我不止一次看到编译器在被告知要优化大小时生成的二进制文件比被告知要优化速度时更大。我总是只使用-O2,有时使用-O3,但要承担随之而来的风险。【参考方案2】:

我从事生物信息学,所以我的建议可能有偏见。也就是说,我总是使用 -O3 开关(用于发布和测试版本,也就是说;通常不用于调试)。诚然,它有一些缺点,即增加编译时间并且通常会增加可执行文件的大小。

但是,第一个因素可以通过良好的构建策略和其他减少整体构建时间的技巧来部分缓解。此外,由于大部分编译实际上是 I/O 绑定的,因此编译时间的增加通常不会那么明显。

第二个缺点,可执行文件的大小,通常根本不重要。

【讨论】:

完全正确 - 正确构建构建并注意 makefile 中的依赖项通常会使编译时间成为问题。这通常有助于提高可执行文件的大小,尽管我见过人们做非常愚蠢的事情导致程序庞大。 我喜欢这个答案,但我要补充一点,它应该很容易运行而无需优化,因为 GDB 以这种方式工作得更好。 根据我的经验,与链接时间相比,编译时间“容易”修复。 (是时候搜索“减少链接时间”的问题了!) 不同意编译与 IO 时间。我发现 -O3 构建非常大的 C++ 文件会占用大量 CPU 时间。我通过将它们连接在一起来构建非常大的 C++ 文件,因为 GCC 4.4 和以前的版本没有 LTO。 @Zan 你的情况是个特例,因为你手动连接了 C++ 文件。您可能知道这可能会极大地减少 IO 开销,因为它可以防止重复读取包含文件。在最好的情况下,这可以有指数级的加速。【参考方案3】:

从不。

使用 -O3 -Wall -Werror -std=[无论你的代码库应该遵循什么]

【讨论】:

作为一个实验,我使用 -O3 和 -Os 构建了 LAME,除了在分析后手动挑选的一些文件使用 -O3。大多数 -Os 版本实际上快了 10% 左右。优化开关并不是一个神奇的性能刻度盘,但将其调高至 11 可以使您的可执行文件更大,使调试更加困难,并引入与优化相关的错误。【参考方案4】:

总是,除非您正在编程并且只想测试您刚刚编写的内容。

【讨论】:

【参考方案5】:

我们通常会设置构建环境,以便我们可以构建使用 -O0 的 debug 构建 和使用 -O3 的 release 构建(构建环境会保留对象和所有配置的库,以便可以在配置之间轻松切换)。在开发过程中,为了更快的构建速度(和更准确的调试信息),主要构建和运行调试配置,并且不太频繁地构建和测试发布配置。

【讨论】:

【参考方案6】:

增加的编译时间真的很明显吗?我一直使用 -O2 作为默认值,更少的东西只会在你的代码中留下很多“摩擦”。另请注意,-O1、-O2 的优化级别往往是经过最佳测试的,因为它们最有趣。 -O0 往往更容易出错,根据我的经验,你可以在 -O2 上很好地调试。如果您对编译器在代码重新排序、内联等方面可以做什么有所了解。

-Werror -Wall 是必要的。

【讨论】:

好吧,以某种方式为我的项目的所有组件设置 -O2 会将总编译时间从 10 分钟更改为 30 分钟 10 分钟到 30 分钟。这足以让你避免它。得分。

以上是关于何时为 gcc 使用 -O2 标志?的主要内容,如果未能解决你的问题,请参考以下文章

何时对多个共享库使用某些优化,例如 -fwhole-program 和 -fprofile-generate

为内联汇编参数打开立即值传播的特定 GCC 标志是啥?

在带有标志选项 -m32 的 gcc-8.2.2 上找不到 std::thread。我正在使用 mingw

在 GCC 中编译时使用 `-Wextra` 标志的缺点

何时使用 ADOX 而不是 ADCX?

如何使用 gnu gcc 标志 -mpc32、-mpc64 和 -mpc80?