在GCC中使用-O3有任何缺点吗

Are there any drawbacks to using -O3 in GCC?

本文关键字:任何 缺点 -O3 GCC      更新时间:2023-10-16

我在各种语言方面做了13年的软件工程师,尽管我现在正在学习C和更高版本的C++。在学习C的过程中,我使用GCC编译器来编译我的程序,我想知道使用-O3或其他优化标志是否有任何问题。如果不测试编译的代码,我的软件是否有可能以无法捕捉的方式崩溃,或者在交叉编译过程中,我可能会无意中为不同的平台搞砸一些东西。

在我盲目地打开这些选项之前,我想知道我能期待什么。此外,当-Oast打开不符合标准的标志时,我倾向于不使用它。我的假设是正确的吗?Ofast很可能会有"副作用"

我看了一眼https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html在我发布这个问题之前。

-O3的唯一缺点应该是无法在调试器中跟踪代码。

-Ofast的使用可能会影响您的一些浮点运算,从而导致舍入错误,但除非您正在运行特别长的浮点计算链,否则您不太可能注意到。

损坏的代码(具有错误指针的代码或具有未定义行为的语句)在不同的优化级别上可能表现不同——许多程序员的第一反应是指责编译器——启用所有警告并修复它们通常会有所帮助。

重要的是要记住,几乎所有的编译器优化都是启发式。换句话说;优化";只是尝试使您的程序更";"最优";,但它很可能会产生相反的效果。仅仅因为-O3应该比-O2好,-O2应该比-O1好——这并不意味着它实际上总是这样工作的。

有时;优化";与使用-O2-O1生成的版本相比,由-O3启用的程序实际上可能会减慢速度。您应该尝试不同级别的优化,看看什么最适合您的特定代码。如果你真的想微调,你甚至可以打开和关闭单个优化

简而言之,是的,使用-O3可能会有一些缺点。我个人观察到,我写的很多东西在-O2上比在-O3上效果更好——但这确实是特定于程序的。


仅供参考,这里还有另一个SO问题,问为什么-O2在特定程序中比-O3给出更好的结果:gcc优化标志-O3使代码比-O2 慢

"我想知道我能期待什么"

我在嵌入式系统中使用C++(主要是vxWorks上的GCC)已经20多年了。我非常尊敬编译作者。


相信你的编译器:IMHO,-O3从未破坏过任何代码。。。但有时也会出现有趣的编码错误。


选择:无论选择-O1还是-O3,团队都必须选择是否"运送您测试的内容,并测试您运送的内容"。与我合作过的团队一直致力于用-O3进行装运和测试。


单步可以是不合作的:在个人实践层面上,当使用-O3代码时,我通常会"放弃"gdb单步。我更多地使用断点,并且在编码选择上有一些细微的变化,以使自动变量(堆栈数据)和类数据更"可见"。(你可以让gdb命令'p'成为你不方便的朋友)。


单步执行是必要的:请注意,尽管我们使用-O3"测试并交付"d,但我们几乎完全使用-O1代码进行调试。


调试是必要的:调试-01和测试-O3之间的权衡是切换两个可执行文件所需的额外重新编译。在-O1中节省的探索、识别和修复代码错误的时间必须弥补2次重建(到-01和回到-O3)。


回归测试自动化:我想说-O3的系统测试(又名集成测试或回归测试)必须更上一层楼,但我真的无法描述它。。。也许我应该建议测试自动化的水平更高(每一次回归测试!)。但我不确定。回归测试的自动化水平可能更多地与团队规模相关,而不是与性能水平相关。


一个"成功"的嵌入式系统可以做两件事。满足要求。而且,我认为更重要的是,在所有人类可见的行为中,它就像一个轻载的桌面。对于任何动作(按钮按下、电缆断开、测试设备引起的错误,甚至是状态灯的轻微变化),结果都没有人为可察觉的延迟-O3有帮助。一个成功的系统是可以做到的。。。我已经看到了。

由于-O3开始移动您的代码以优化它,在某些情况下,您可能会看到您的结果不同或中断。

如果您使用-O3测试代码的正确性,并发现无法调试的问题,建议切换到-O0以查看是否得到相同的行为。