我从各种来源(尽管主要来自我的一位同事)听说,在 g++ 中以 -O3
的优化级别进行编译在某种程度上是“危险的”,除非证明是必要的,否则一般应避免。
这是真的吗?如果是,为什么?我应该坚持 -O2
吗?
原文由 Matt Dunn 发布,翻译遵循 CC BY-SA 4.0 许可协议
我从各种来源(尽管主要来自我的一位同事)听说,在 g++ 中以 -O3
的优化级别进行编译在某种程度上是“危险的”,除非证明是必要的,否则一般应避免。
这是真的吗?如果是,为什么?我应该坚持 -O2
吗?
原文由 Matt Dunn 发布,翻译遵循 CC BY-SA 4.0 许可协议
是的,O3 更麻烦。我是一名编译器开发人员,在构建我自己的软件时,我发现了由 O3 生成有缺陷的 SIMD 汇编指令引起的清晰而明显的 gcc 错误。据我所见,大多数生产软件都附带 O2,这意味着 O3 在测试和错误修复方面受到的关注较少。
可以这样想:O3 在 O2 之上添加了更多转换,这在 O1 之上添加了更多转换。从统计学上讲,更多的转换意味着更多的错误。对于任何编译器都是如此。
原文由 David Yeager 发布,翻译遵循 CC BY-SA 3.0 许可协议
3 回答2k 阅读✓ 已解决
2 回答3.9k 阅读✓ 已解决
2 回答3.2k 阅读✓ 已解决
1 回答3.2k 阅读✓ 已解决
1 回答2.7k 阅读✓ 已解决
3 回答3.5k 阅读
3 回答505 阅读✓ 已解决
在 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时必须小心,它指出:
这使我得出结论, -O3 旨在完全符合标准。