我已经成为一名软件工程师已有13年的各种语言,尽管我现在正在进入C和后来的C ++。当我学习C时,我使用GCC编译器来编译我的程序,并且我想知道是否有使用-O3或其他优化标志的问题。我的软件是否有可能在不测试已编译代码的情况下以我无法捕获的方式中断,或者在交叉编译期间,我可能会无意中混淆了某个不同的平台。
在我盲目地打开这些选项之前,我想知道我能期待什么。此外,由于-Ofast打开了不符合标准的标志,我倾向于不使用它。在我的假设中,我是否正确--Ofast很可能会产生副作用?"
在我发布此问题之前,我已经浏览了https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html。
答案 0 :(得分:9)
-O3
的唯一缺点应该是无法在调试器中遵循代码。
使用-Ofast
可能会影响某些浮点运算导致舍入错误,但除非您运行特定的长浮点计算链,否则您不太可能注意到。
破坏的代码(带有错误指针的代码或具有未定义行为的语句)可能在不同的优化级别上表现不同 - 许多程序员的第一反应是责怪编译器 - 启用所有警告并修复它们通常会有所帮助。
答案 1 :(得分:6)
重要的是要记住几乎所有的编译器优化都是启发式。换句话说,“optmization”只是一个尝试,使你的程序更“理想”,但它可能会产生相反的效果。仅仅因为-O3
应该优于-O2
,而-O2
应该优于-O1
- 这并不意味着事实上它总是如此有效。
与使用-O3
或-O2
生成的版本相比,有时-O1
启用的“优化”可能会降低您的程序速度。您应该尝试不同级别的优化,以查看哪种方法最适合您的特定代码。如果你真的想对它进行微调,你甚至可以打开和关闭个人验证。
所以简而言之 - 是的,使用-O3
会有不利之处。我个人观察到我写的很多内容在使用-O2
而不是-O3
时效果更好 - 但这确实与程序有关。
仅供参考,这是另一个SO问题,询问为什么-O2
为特定计划提供的结果优于-O3
:gcc optimization flag -O3 makes code slower then -O2
答案 2 :(得分:1)
由于-O3开始移动代码以优化它,在某些情况下,您可能会看到结果不同或中断。
如果使用-O3测试代码的正确性并找到无法调试的问题,建议切换到-O0以查看是否获得相同的行为。
答案 3 :(得分:1)
“我想知道我能期待什么”
我已经在嵌入式系统中使用C ++(主要是vxWorks上的GCC)超过20年。我非常尊重编译器编写者。
相信你的编译器:恕我直言,-O3从未破坏任何代码......但有时会发现有趣的编码错误。
选择:团队必须选择是否或不来“运送您测试的内容,并测试您发货的内容”,无论选择-O1还是-O3。我与之合作过的团队一直致力于使用-O3进行发货和测试。
单步可以是不合作的:在个人实践层面,当使用-O3代码时,我通常会“放弃”gdb单步。我更多地使用了断点,并且编码选择略有不同,使自动变量(堆栈数据)和类数据更“可见”。 (你可以让gdb命令'p'成为你不方便的朋友。)
单步是必要的:请注意,即使我们使用-O3“测试并发货”,我们几乎只使用-O1代码进行调试。
调试是必要的:调试-01之间的权衡,但测试和运输-O3是切换两个可执行文件所需的额外重新编译。在-O1中保存以探索,识别和修复代码错误的时间必须构成2次重建(至-01并返回-O3)。
回归测试自动化:我想说-O3的系统测试(也称为集成测试或回归测试)必须提升一个档次,但我无法真正描述它......或许我应该推荐这个级别测试自动化程度更高(每一个REGRESSION TESTs!)。但我不确定。回归测试的自动化级别可能更多地与团队规模相关,而不是与绩效水平相关。
'成功'的嵌入式系统可以做两件事。它满足要求。并且,我认为更重要的是,在所有人类可见的行为中,它就像一个轻载的桌面。对于任何动作(按钮按压,电缆断开,测试设备引起的误差,或甚至低状态的灯光变化),结果都没有人类可察觉的延迟。 -O3有帮助。一个成功的系统可以完成......我已经看过了。