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