当前位置: 首页 > 知识库问答 >
问题:

我应该优化多少?

阙阳
2023-03-14

关于编译器(GCC)所做的优化,标准做法是什么?每个选项(-O、-O1、-O2、-O3、-Os、-s、-fexpensive-optimizations)有什么不同,我如何决定什么是最优的?

共有2个答案

厉熠彤
2023-03-14

Linux内核的Makefile提供了-O2,以及-Os。如果没有进一步的细节,任何一个都是合适的。

-Os针对小型存储进行了优化。由于如今CPU比主存储器快得多,因此即使在大型机器上,针对小型存储进行优化也是有意义的——等待缓存从主存储器填充所花费的任何时间都是浪费时间。因此,通过编译以提高空间效率来充分利用指令缓存,也许执行时间也会缩短。

< code>-O2运行所有的“常规优化”,所选择的优化将是安全的。(我听说有些< code>-O3优化并不总是安全的,但这可能是因为Linux内核运行时有一些常见应用程序没有的约束。)

当然,最好的答案是用多级优化来编译你的软件;时间编译软件需要多长时间,时间软件运行一个代表性的基准测试需要多长时间。测量它们总共使用了多少内存。

然后选择编译速度、运行时速度和运行时内存使用的“最佳”组合。您可能想要最快的编译,或者您可能想要最快的运行时间,或者您可能试图从虚拟托管服务提供商那里获得更少的内存以节省资金。

在不进行任何测量的情况下,选择-O2可能是公平的。

谢昊乾
2023-03-14

通常-O2是首先尝试的一个很好的优化级别。

然而,如果你想得到最好的结果,你最终会尝试很多优化级别,因为你无法事先判断哪个级别最适合你的应用。

另请注意,优化结果应因每个 CPU 而异(在某些 CPU 上,针对大小进行优化实际上可能比优化速度产生更好的速度)。

仅供将来参考,以下是每个级别的简要说明(您可以在文档 http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html 中找到完整的说明):

-O(与 -O1 相同):使用 -O,编译器会尝试减少代码大小和执行时间,而不执行任何需要大量编译时间的优化。

-O2:进一步优化。GCC执行几乎所有支持的优化,不涉及空间速度的权衡。与-O相比,该选项增加了编译时间和生成代码的性能。

-O3:进一步优化。-O3 打开 -O2 指定的所有优化,还打开 -finline 函数、-funswitch-循环、-预测-共生、-fgcse-重新加载后、-ftree-矢量化、-ftree-部分-pre 和 -fipa-cp-克隆选项。

-Os:优化大小。-Os启用通常不会增加代码大小的所有-O2优化。它还执行旨在减少代码大小的进一步优化。

-Ofast:无视严格的合规标准-Ofast支持所有-O3优化。它还启用了对所有符合标准的程序无效的优化。它打开-ffast数学和Fortran特定的-fno保护parens和-fstack数组。如果您使用多个-O选项,无论有没有级别编号,最后一个这样的选项是有效的。

 类似资料:
  • 问题内容: 有一个有趣的选择: 通过内联静态,最终和私有方法来优化编译代码。请注意,您的班级可能会变大。 该选项似乎并不流行(隐藏?),我今天才在CodeCup 2014页面 上发现了它。 在官方文档中也没有提及。 在接受类似问题的答案中,我们可以看到: Java中的优化主要由JIT编译器在运行时完成。因此,没有必要试图指示它在编译时优化某种方式(无论如何它仅创建字节码)。JIT几乎肯定会在现场做

  • 有一个有趣的选项: 通过内联静态、最终和私有方法优化编译代码。请注意,您的类可能会变得更大。 这个选项似乎不流行(隐藏?),我今天刚刚在CodeGlass 2014页面上发现了它。 在官方文档中没有提到,也没有在...奇怪。 在类似问题的公认答案中,我们可以看到: Java 中的优化主要由 JIT 编译器在运行时完成。因此,尝试指示它在编译时以某种方式进行优化是没有意义的(无论如何,当它只创建字节

  • Docker教程经常说我可以运行更多容器,以提高我的webapp的可用性。然而,这是一个非常宽泛的声明,并没有解释在不同的情况下应该运行多少个容器。我如何知道我是否需要1、5、10、100或1000个容器实例? 示例-我只有一台服务器,正在使用docker运行nginx和php fpm。每个容器一个。有了这个简单的设置,我的webapp就可以正常工作,而且看起来很灵敏。(在同一台服务器上)增加额外

  • 这是用构建的好例子吗?有理由不这样做吗?我从未真正见过一个程序,无论它花多少时间在I/O上,都是为了大小而编译的。

  • 问题内容: 我有一个可以为其创建一个(或多个)实例的实例。我正在使用Servlet环境,并且已经将一个EntityManagerFactory连接到Servlet(通过Servlet上下文),该Servlet在Servlet的生命周期中(因此,对于所有用户)都共享。 我可以执行以下操作之一: 在我的Servlet的生存期内创建一个EntityManager(例如,在所有用户之间共享) 为每个用户创

  • 问题内容: 在这个答案中,它表示(暗示)无论如何都将String连接优化到StringBuilder操作中,因此,当我编写代码时,是否有任何理由在源代码中编写StringBuilder代码?请注意,我的用例与OP的问题不同,因为我正在串联/附加数十万行。 为了使自己更清楚:我很清楚每种代码的区别,只是我不知道是否值得实际编写StringBuilder代码,因为它的可读性较低,并且当它的较慢的表亲S