268

我从各种来源(尽管主要来自我的一位同事)听说,使用-O3g++ 中的优化级别进行编译在某种程度上是“危险的”,除非证明有必要,否则一般应避免。

这是真的吗?如果是,为什么?我应该坚持-O2吗?

4

5 回答 5

260

在 gcc(2.8 等)的早期和 egcs 时代,redhat 2.96 -O3 有时会出现很多问题。但这是十多年前的事了,-O3 与其他级别的优化(在 buggyness 中)没有太大区别。

然而,由于更严格地依赖于语言的规则,尤其是极端情况,它确实倾向于揭示人们依赖未定义行为的情况。

作为个人说明,我多年来一直使用 -O3 在金融领域运行生产软件,并且还没有遇到如果我使用 -O2 就不会出现的错误。

根据大众的需求,这里增加一个:

-O3 尤其是附加标志,如 -funroll-loops(-O3 未启用)有时会导致生成更多机器代码。在某些情况下(例如在具有异常小的 L1 指令缓存的 CPU 上),这可能会导致速度变慢,因为例如某些内部循环的所有代码现在不再适合 L1I。通常 gcc 会努力不生成这么多代码,但由于它通常会优化通用案例,因此可能会发生这种情况。特别容易出现这种情况的选项(如循环展开)通常不包含在 -O3 中,并在手册页中相应地标记。因此,使用 -O3 生成快速代码通常是一个好主意,并且仅在适当时(例如,当分析器指示 L1I 未命中时)回退到 -O2 或 -Os(尝试优化代码大小)。

如果您想将优化发挥到极致,您可以通过 --param 在 gcc 中调整与某些优化相关的成本。另外请注意,gcc 现在能够将属性放在仅控制这些函数的优化设置的函数中,因此,当您发现 -O3 在一个函数中存在问题时(或只想为该函数尝试特殊标志),您不需要使用 O2 编译整个文件甚至整个项目。

otoh似乎在使用-Ofast时必须小心,它指出:

-Ofast 启用所有 -O3 优化。它还支持并非对所有符合标准的程序都有效的优化。

这使我得出结论, -O3 旨在完全符合标准。

于 2012-07-18T16:40:09.277 回答
50

在我有点曲折的经验中,应用-O3到整个程序几乎总是会使它变慢(相对于-O2),因为它打开了激进的循环展开和内联,使程序不再适合指令缓存。对于较大的程序,-O2相对于-Os!

for 的预期使用模式-O3是,在对程序进行概要分析之后,您手动将其应用于少数包含关键内部循环的文件,这些内部循环实际上受益于这些激进的空间换速度权衡。较新版本的 GCC 具有配置文件引导的优化模式,可以 (IIUC) 选择性地将-O3优化应用于热功能 - 有效地自动化此过程。

于 2013-11-14T18:46:17.693 回答
17

-O3 选项除了低级别“-O2”和“-O1”的所有优化之外,还启用更昂贵的优化,例如函数内联。“-O3”优化级别可以提高生成的可执行文件的速度,但也可以增加其大小。在这些优化不利的某些情况下,此选项实际上可能会使程序变慢。

于 2012-07-18T18:12:48.350 回答
16

是的,O3 更麻烦。我是一名编译器开发人员,在构建我自己的软件时,我发现了由 O3 生成有缺陷的 SIMD 汇编指令引起的清晰而明显的 gcc 错误。据我所见,大多数生产软件都附带 O2,这意味着 O3 在测试和错误修复方面受到的关注较少。

Think of it this way: O3 adds more transformations on top of O2, which adds more transformations on top of O1. Statistically speaking, more transformations means more bugs. That's true for any compiler.

于 2016-08-25T20:17:14.183 回答
3

最近我在使用g++. 该问题与 PCI 卡有关,其中寄存器(用于命令和数据)由内存地址表示。我的驱动程序将物理地址映射到应用程序中的一个指针,并将其提供给被调用的进程,它可以像这样使用它:

unsigned int * pciMemory;
askDriverForMapping( & pciMemory );
...
pciMemory[ 0 ] = someCommandIdx;
pciMemory[ 0 ] = someCommandLength;
for ( int i = 0; i < sizeof( someCommand ); i++ )
    pciMemory[ 0 ] = someCommand[ i ];

该卡没有按预期运行。当我看到程序集时,我明白编译器只写入someCommand[ the last ]pciMemory,省略了所有前面的写入。

总而言之:在优化时要准确和专注。

于 2013-03-25T15:01:43.287 回答