欢迎光临散文网 会员登陆 & 注册

你真的了解编译器的优化等级吗?

2023-04-28 10:40 作者:亿道电子  | 我要投稿

导语:项目开发过程中我们为什么要选择编译的优化等级?


在目前的嵌入式开发过程中,编译的时候编译器都具有多项的优化等级,其目的是为了减少代码大小或者提高应用程序的性能。不同的优化等级,有着不同的优化目标。所以对于某个目标进行优化的时候,会对其他目标产生一些影响。优化等级的选择是在不同的优化目的中寻找一个平衡点。


一、那么目前有哪些优化等级?对应优化等级所优化的是那部分的内容?

1.-O0:没有优化

使用-O0 结果可以加快编译和构建时间,但比其他优化等级生成的代码要慢。与其他优化等级相比,代码大小和堆栈使用率明显更高。生成的代码与源代码紧密相关,但是生成的代码量更大,包括无用的代码。

2.-O1:有限优化

在编译器中启用核心优化。此优化等级提供了良好的调试体验,并具有比-O0更好的代码质量,堆栈使用率也提高了。

3.-O2:优化速度

有更高的性能优化。增加了一些新的优化,并更改了优化的启发式方法。这是编译器可能生成矢量指令的第一个优化等级。它会降低调试体验,并且由于许多循环展开和函数内联,代码大小将增加。

4.-O3:优化速度

有更高的性能优化。此优化等级允许进行需要大量编译时分析和资源的优化。-O3指示编译器针对生成的代码的性能进行优化,而忽略生成的代码的大小,这可能会导致代码大小增加,比-O2生成的代码更大。但速度会比比-O2快

5.-Os:平衡的优化

目的是在不显着增加代码大小的情况下提供高性能,即速度的优化和代码大小的增加是合理的。根据你的应用程序,提供的性能可能类似于 -O2或-O3。

6.-Oz:纯粹优化代码大小

目的是提供尽可能小的代码量。在开发过程中,建议使用此选项以获得最佳代码大小。但是,此优化等级会降低调试体验。

7.-Ofast:

从-O3级开始执行优化。该等级还执行其他进一步的优化,可能会违反严格遵守语言标准的要求。与-O3相比,该等级会降低调试体验,并可能导致代码大小增加。

8.-Omax:最大程度的优化

执行最大限度的优化,并专门针对性能优化。它启用了-Ofast和链接时间优化(LTO)的所有优化。在此优化等级上,编译器是有可能会违反严格遵守语言标准的规定。使用此优化等级可获得最快的性能。与-Ofast相比,该等级会降低调试体验,并可能导致代码大小增加。


二、优化等级之间的比较

1.-O1与-O0相比:

(1)-O1启用优化,这可能会降低调试信息的完整度。

(2)-O1启用了内联,这意味着回溯可能不会提供读取源代码所期望的开放函数激活堆栈。

(3)-O1不会调用没有使用或没有预期调用的函数,代码量更小。

2.-O2与-O1相比:

(1)-O2执行的循环展开量(一种牺牲程序的尺寸来加快程序的执行速度的优化方法)可能会增加。

(2)-O2可以为简单循环和独立标量运算的相关序列生成矢量指令。

3.-O3与-O2相比:

(1)-O3执行的循环展开量增加。

(2)-O3在编译器流水线后期中启用更积极的指令优化。

4.-Os与-O3相比:

(1)-Os与-O3相比,可减少代码大小。但会降低调试体验。

(2)显着降低了执行的循环展开量。

5.-Oz与-Os相比:

(1)编译器仅针对代码大小进行优化,而忽略性能优化,这可能会导致代码变慢。

(2)未禁用功能内联。在某些情况下,内联可能会整体上减少代码大小,例如,如果一个函数仅被调用一次。仅当预期代码大小会减小时,才将内联启发式方法调整为内联式。

(3)禁用可能会增加代码大小的优化,例如循环展开和循环矢量化。

(4)循环是作为while循环而不是do-while循环生成的。

6.-Omin与-Oz相比:

(1)-Omin启用了一组基本的链接时间优化(LTO),旨在删除未使用的代码和数据,同时也试图优化全局内存访问。

(2)-Omin支持虚函数消除,这对c++用户来说是一个特别的好处。


三、那么说的那么多,我们到底要怎么选择优化等级呢?

简单来说,

  • 想要工程代码小,那就-Oz和-Omin

  • 想要工程有更好的性能,那就选-O2,-O3,-Ofast,-Omax

  • 想要良好的调试过程,那就选-O1

  • 想要源代码和生成的代码之间有更好的相关性或者想要更快的编译速度,那就-O0

  • 又想要工程代码小还要有好的性能,那就-Os


你真的了解编译器的优化等级吗?的评论 (共 条)

分享到微博请遵守国家法律