【问题标题】:GCC optimization levels. Which is better?GCC 优化级别。哪个更好?
【发布时间】:2016-01-01 15:39:54
【问题描述】:

我关注的是 GCC 编译程序的 CPU/内存消耗。

执行用O3编译的代码,总是那么贪心吗?

有没有科学的参考或规范可以说明不同级别的Mem/cpu消耗差异?

研究这个问题的人经常关注这些优化对执行时间、编译代码大小和能量的影响。但是,我找不到太多关于资源消耗的工作(通过启用优化)。

提前致谢。

【问题讨论】:

  • "有没有科学的参考或规范表明不同级别的Mem/cpu消耗的差异?"我的建议是在您自己的代码上对其进行测试,看看会发生什么。正如@BasileStarynkevitch 所说,03 优化并不一定意味着性能将优于 02。由于-fpredictive-commoning 标志,03 存在并发问题(如果执行不正确)。此外,优化程度越高,GCC 遵循的规则就越严格,如果代码以某种方式依赖于未定义的行为,则更容易暴露关键错误。
  • 我看到的 GCC 和其他一些编译器的问题是它们严格由源代码决定。我知道的一个 TI 编译器可以生成人类可读的关于性能限制因素的反馈消息,如寄存器或 ALU 使用、结构不良的循环控制,并帮助程序员相应地调整源。优化优化设置不是真正的优化。优化就是找出需要花费太多时间的事情并采取相应措施。
  • MILEPOST 项目做了一些非常相关的事情......
  • 我还是不明白你的意思。你住在哪个国家?您是否有资源(例如 50 万欧元或美元)来实现您的目标?如果您住在欧洲,也许您的想法或愿望可能会成为某些协作研发项目的一部分(例如 H2020、ITEA ......)。如果是这样,请通过电子邮件与我联系...
  • 但是您没有定义什么是内存消耗:动态堆栈大小、堆要求、缓存未命中、代码大小?

标签: gcc optimization compilation performance-testing compiler-optimization


【解决方案1】:

不,没有绝对的方法,因为optimization in compilers 是一门艺术(甚至没有很好的定义,可能是undecidableintractable)。

但首先需要一些指导:

  • 确保您的程序正确在优化任何内容之前没有错误,因此请调试和测试您的程序

  • 拥有精心设计的测试用例和具有代表性的基准测试(参见this)。

  • 确保您的程序没有undefined behavior(这很棘手,请参阅this),因为GCC 会奇怪地优化(但通常是正确的,根据C99 或 C11 标准)如果您的代码中有 UB;在调试阶段使用-fsanitize=style 选项(以及gdbvalgrind ....)。

  • profile您的代码(在各种基准测试中),特别是找出哪些部分值得优化;通常(但并非总是)大部分 CPU 时间发生在一小部分代码中(经验法则:80% 的时间花费在 20% 的代码中;在某些应用程序上,例如 gcc 编译器,这是不正确的,请检查与gcc -ftime-report 要求gcc 显示在各种编译器模块中花费的时间)....大部分时间"premature optimization is the root of all evil"(但这句格言也有例外)。

  • 改进您的源代码(例如谨慎正确地使用restrictconst,添加一些pragmasfunctionvariable 属性,也许明智地使用一些GCC builtins __builtin_expect, __builtin_prefetch -见this-, __builtin_unreachable...)

  • 使用最新的编译器。 GCC 的当前版本(2015 年 10 月)是 5.2(和 2018 年 6 月的 GCC 8),并且在优化方面不断取得进展;您可以考虑从源代码编译 GCC 以获得最新版本。

  • 在编译器中启用所有警告 (gcc -Wall -Wextra),并尽量避免所有警告;某些警告可能仅在您要求优化时出现(例如使用-O2

  • 通常,使用-O2 -march=native(或者-mtune=native,我假设你不是cross-compiling,如果你确实添加好的-march选项...)编译并以此为基准测试你的程序

  • 考虑link-time optimization,通过编译和链接-flto和相同的优化标志。例如,将CC= gcc -flto -O2 -march=native 放入您的Makefile(然后从您的CFLAGS 中删除-O2 -mtune=native)...

  • 也可以试试-O3 -march=native,通常情况下(但并非总是如此,有时使用-O2 的代码可能比使用-O3 的代码稍快,但这并不常见)你可能会比-O2 得到一点改进

  • 如果要优化生成的程序大小,请使用-Os而不是-O2-O3;更一般地说,不要忘记阅读文档的Options That Control Optimization 部分。我猜-O2-Os 都会优化堆栈使用(这与内存消耗非常相关)。并且一些 GCC 优化能够避免malloc(这与堆内存消耗有关)。

  • 你可以考虑profile-guided optimizations-fprofile-generate-fprofile-use-fauto-profileoptions

  • 深入了解GCC 的文档,它有许多optimizationcode generation 参数(例如-ffast-math-Ofast ...)和parameters,你可能会花几个月的时间尝试一些更多;请注意,其中一些并不严格符合 C 标准!

  • 即使在优化时,最近的 GCCClang 也可以发出 DWARF 调试信息(如果应用了强优化,则以某种方式“近似”),因此传递 -O2-g 可能是值得的(您仍然可以在优化的可执行文件上使用 use the gdb debugger 进行一些痛苦的操作)

  • 1234563但这很困难(您需要了解 GCC 内部表示和组织)并且可能很少值得,除非在非常特殊的情况下(当您可以证明花费数月时间来改进优化的情况)
  • 您可能想了解程序的堆栈使用情况,因此请使用-fstack-usage

  • 您可能想了解发出的汇编代码,使用 -S -fverbose-asm 和优化标志(并查看生成的 .s 汇编文件)

  • 您可能想了解 GCC 的内部工作原理,使用各种 -fdump-* 标志(您将获得数百个转储文件!)。

当然,上面的待办事项列表应该以迭代和敏捷的方式使用。

对于memory leaks 错误,请考虑valgrind 和几个-fsanitize= debugging options。另请阅读garbage collection(和GC handbook),尤其是Boehm's conservative garbage collector,以及编译时垃圾回收技术。

阅读 GCC 中的 MILEPOST project

还要考虑OpenMPOpenCLMPImulti-threading 等...请注意,parallelization 是一门高难度的艺术。

请注意,即使是 GCC 开发人员也经常无法预测此类优化的效果(对生成的二进制文件的 CPU 时间)。不知何故,优化是一门黑色艺术。

也许gcc-help@gcc.gnu.org 可能是在GCC 中询问有关优化的更具体、准确和集中的问题的好地方

您也可以通过basileatstarynkevitchdotnet 与我联系,提出更集中的问题...(并提及您最初问题的网址)

关于优化的科学论文,你会发现很多。从ACM TOPLASACM TACO 等开始...搜索迭代编译器优化等...并更好地定义您想要优化的资源(内存消耗几乎没有... .).

【讨论】:

  • -mtune=native 不是和-march=native 类似吗?
  • (在 x86 上)-mtune 会影响 gcc 认为每条指令所需的时间。 -march 影响可用指令列表(如 avx2)。除非您覆盖它,否则 -march 意味着等效的 -mtune。
  • @BasileStarynkevitch 资源消耗如何?我的意思是CPU和内存消耗?我对这个主题有过早的研究吗?例如,如果我想在资源消耗方面测试 00-03,是否有任何权衡?另外,是否有任何关于资源使用的集群优化选项的尝试?
  • @staticx:您应该编辑您的问题以改进它。您是在谈论编译期间GCC 编译器内部的 CPU 和内存消耗,还是编译后的应用程序内部的 CPU 和内存消耗?
  • @BasileStarynkevitch 对不起。我更新了问题。你可以检查一下。我正在检查已编译应用程序的 CPU/内存消耗
猜你喜欢
  • 2012-09-16
  • 2011-06-14
  • 2010-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-15
  • 2011-10-13
  • 2017-02-18
相关资源
最近更新 更多