CONTACT
时间:2024-02-28 00:42:11 点击量:
c语言编译器优化选项有 0/1/2/3 四个等级的优化,为什么不直接默认最高等级优化?
GCC提供选项控制代码的优化等级:
这些选项可以实现不同程度的优化。
没有任何优化选项的话,编译时的目标是降低编译成本,并使调试产生预期的结果。语句是独立的:如果你使程序停止在语句之间设置的断点处,你可以改变任何变量的值或者改变程序计数器的值使程序执行任意函数中的语句并得到源代码中期望的结果。
打开优化标志使编译器尝试以编译时间和可能的调试程序的能力为代价来改进性能和/或代码大小。
编译器根据程序的信息执行优化。 一次编译多个文件生成单个可执行文件的模式允许编译器在编译每个文件时使用从所有文件中获取的信息。
并非所有优化都由标志直接控制。
1.优化花时间(其实C++的优化更加花时间,比如十几层模板的库,不过最花时间的可能是LinkTimeOptimization)
2.优化妨碍debug(优化会省去一些操作,把一些变量优化到寄存器或直接优化掉,函数调用也会优化掉/内联。直观表现就是debug时部分变量值不显示,断点打不上)
所以默认开最高等级优化是不可取的,甚至默认开优化都不见得是件好事。
首先一定要有不优化和优化两个选项。因为优化会改代码,所以需要一个直译来看看到底是否代码的问题。这是0级。
其次,有的优化只在一个方面有优势,比如一般是用空间换时间,但有时也需要时间换空间。这是1和2级
最后,有各别优化,只在一些情况下有用,一些情况下代码会出错。这就是3级优化。
使用方面,我的建议是直接开-O2,有问题了用O0调试。不要在0级调好了程序,上2级优化挂了,那很难找出问题。-O2编译结果有问题,99.9%是代码问题。
对自己的代码有把握的可以直接上-O3,按-O3写代码可以学到语法中最后的精髓。
如果-O2和-O1的代码大小区别比较大,尺寸又非常重要,那么可以上-O1。
优化处理是编译系统中一项比较艰深的技术。它涉及到的问题不仅同编译技术本身有关,而且同机器的硬件环境也有很大的关系。优化一部分是对中间代码的优化。这种优化不依赖于具体的计算机。另一种优化则主要针对目标代码的生成而进行的。
对于前一种优化,主要的工作是删除公共表达式、循环优化(代码外提、强度削弱、变换循环控制条件、已知量的合并等)、复写传播,以及无用赋值的删除,等等。
后一种类型的优化同机器的硬件结构密切相关,最主要的是考虑是如何充分利用机器的各个硬件寄存器存放有关变量的值,以减少对于内存的访问次数。另外,如何根据机器硬件执行指令的特点(如流水线、RISC、CISC、VLIW等)而对指令进行一些调整使目标代码比较短,执行的效率比较高,也是一个重要的研究课题。
经过优化得到的汇编代码必须经过汇编程序的汇编转换成相应的机器指令,方可能被机器执行。
gcc默认提供了5级优化选项的集合:
-O0:无优化(默认)
-O和-O1:使用能减少目标文件大小以及执行时间并且不会使编译时间明显增加的优化.在编译大型程序的时候会显著增加编译时内存的使用.
-O2: 包含-O1的优化并增加了不需要在目标文件大小和执行速度上进行折衷的优化.编译器不执行循环展开以及函数内联.此选项将增加编译时间和目标文件的执行性能.
-Os:专门优化目标文件大小,执行所有的不增加目标文件大小的-O2优化选项.并且执行专门减小目标文件大小的优化选项.
-O3: 打开所有-O2的优化选项并且增加 -finline-functions, -funswitch-loops,-fpredictive-commoning, -fgcse-after-reload and -ftree-vectorize优化选项.
前面好像有人说到了两点,一个是优化需要的时间比较长,开发的时候开优化有些浪费时间,另一个是优化会修改你的原代码,调试的时候不方便。
对于第一点,我是前几天才稍微体会到的。我写的是C++,稍微(真的是稍微)用了一点编译期计算的功能。这段代码在无优化的情况下编译只需要一两秒(当然编译期计算被忽略了),但如果打开优化那就刺激了,,,反正我等了十几分钟它也没编译出来。
对于第二点,我是在知乎上看到的回答。那个问题大概是“编程实现从一加到一百和从一百加到一,哪个效率更高?”。回答是:没区别,在打开优化的情况下,二者都是直接输出5050。所以这个你要怎么调试?
地址:海南省海口市玉沙路58号 电话:0898-88889999 手机:13988889999
Copyright © 2012-2018 天辰-天辰平台-天辰中国加盟站 ICP备案编:琼ICP备88889999号