0

我专注于GCC编译程序的CPU /内存消耗。GCC优化级别。哪个更好?

使用O3编译的执行代码在资源方面总是如此贪婪?

是否有任何科学参考或规格说明显示不同级别的Mem/cpu消耗差异?

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

在此先感谢。

+0

关于优化工作(和发表研究论文)的人不关注编译时间。他们专注于编译和优化代码的执行时间。 –

+0

你有什么样的代码?科学HPC数字代码? –

+1

“是否有任何科学参考或规格说明显示不同级别的Mem/cpu消耗的差异?”我的建议是在你自己的代码上测试它,看看会发生什么。正如@BasileStarynkevitch所指出的那样,03优化并不一定意味着性能会比02. 03好,因为'-fpredictive-commoning'标志会导致并发问题(如果做得不正确)。此外,更严格的GCC遵循规则的优化程度越高,如果代码依赖未定义的行为,则更容易暴露重要的错误。 – rbaleksandar

回答

7

不,没有绝对的办法,因为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,并在优化方面不断取得进展;你可以考虑从其源代码编译GCC来获得最新版本。

  • 在编译器中启用所有警告gcc -Wall -Wextra),并尽力避免所有警告;当你问的优化(例如用-O2

  • 通常一些警告可能只会出现,与-O2 -march=native编译(或者-mtune=native,我认为你是不是cross-compiling,如果你添加好-march选项...)和基准与

  • 程序通过编译和链接-flto和相同的优化参数考虑link-time optimization。例如,把CC= gcc -flto -O2 -march=nativeMakefile(然后将其删除您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的文件,它有许多optimization & code generation参数(如-ffast-math-Ofast ...)和parameters,你可以花几个月尝试一些更多的;注意其中一些不严格符合C标准!如果您有很多时间花费(数周或数月),则可以使用MELT来定制GCC以添加您自己的新(特定于应用程序的)优化通行证;如果您有足够的时间花费(数周或数月),则可以使用MELT来定制GCC。但这很难(你需要了解GCC内部表示和组织),并且可能很少有价值,除非在特定情况下(当你可以证明花费你几个月的时间来改进优化)

  • 你可能想要了解你的程序的堆栈使用,所以使用-fstack-usage

  • 你可能需要了解所发出的汇编代码中,除了优化标志的使用-S -fverbose-asm(并期待被制成的.s汇编文件)

  • 你可能想了解in 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时间)。不知何故,优化是一种黑色艺术。

也许[email protected]可能是一个很好的地方,要求更具体的&关于优化精确和集中的问题在GCC

你也可以与我联系basilestarynkevitchnet更注重问题...(并提及您的原始问题的网址)

对于关于优化的科学论文,您会发现很多。开始于ACM TOPLAS,ACM TACO等...搜索迭代编译器优化等....并更好地定义你想优化的资源(内存消耗意味着什么都没有....)。

+0

不是'-mtune = native'类似于-march = native'吗? –

+0

(在x86上)-mtune会影响gcc认为每条指令需要的时间。 -march影响可用的指令列表(如avx2)。除非你重写它,-march意味着等价的调音。 –

+0

@MarcGlisse:谢谢,改进我的回答 –