c-G优化超过-O3 / -Ofast

问题

我们有一个中型程序用于模拟任务,我们需要优化。我们已经做了我们最好的优化源代码到我们的编程技能的极限,包括GprofValgrind的分析。

当最终完成后,我们想要在几个系统上运行程序几个月。因此,我们真的有兴趣将优化推向极限。

所有系统将在相对较新的硬件(Intel i5或i7)上运行Debian / Linux。

问题

什么是可能的优化选项使用最新版本的g,超越-O3 / -Ofast?

我们也对昂贵的小型优化感兴趣,这将从长远来看支付。

我们现在使用什么

现在我们使用以下g优化选项:

> -Ofast:最高“标准”优化级别。包含的 – 算术在我们的计算中没有引起任何问题,所以我们决定去使用它,尽管是非标准的。
> -march = native:启用所有CPU特定指令的使用。
> -flto以允许链接时间优化,跨不同编译单元。

大多数答案建议替代解决方案,如不同的编译器或外部库,这很可能带来大量的重写或集成工作。我将努力坚持问题的要求,并专注于可以通过激活编译器标志或对代码做最小的修改,根据OP的要求单独做GCC。这不是一个“你必须这样做”的答案,但更多的GCC调整的集合已经为我做得很好,如果他们在你的具体上下文相关,你可以尝试。

关于原始问题的警告

在详细介绍之前,关于这个问题的一些警告,通常对于会来的人来说,读取问题并说“OP正在优化超过O3,我应该使用与他相同的标志!

> -march = native启用特定于给定CPU体系结构的指令的使用,并且不一定在不同的体系结构上可用。如果在具有不同CPU的系统上运行,或者运行速度明显变慢(因为这也启用了mtune = native),程序可能根本不工作,因此如果决定使用它,请注意这一点。更多信息here
> -Ofast,正如你所说,启用一些非标准兼容的优化,所以它也应谨慎使用。更多信息here

其他GCC标志试用

不同标志的详细信息列在here

> -Ofast启用-ffast-math,从而启用-fno-math-errno,-funsafe-math-optimizations,-ffinite-math-only,-fno-rounding-math,-fno-signaling-nans和-fcx有限范围。您可以通过选择性地添加一些额外的标志(例如-fassociative-math,-freciprocal-math,-fno-signed-zeros和-fno-trapping-math)来进一步了解浮点计算优化。这些不包括在-Ofast中,并且可以在计算时提供一些额外的性能提升,但是您必须检查他们是否真正受益,并且不中断任何计算。
> GCC还具有一些其他优化标志,它们没有通过任何“-O”选项启用。它们被列为“可能产生破碎代码的实验选项”,因此,应谨慎使用它们,并通过测试正确性和基准测试来检查它们的效果。然而,我经常使用-frename-registers,这个选项从来没有产生不想要的结果,我倾向于给出一个显着的性能提高(即可以测量基准时)。这是一种非常依赖于处理器的标志类型。 -funroll-loops也有时会得到好的结果,但它依赖于你的实际代码。

PGO

GCC具有Profile-Guided Optimisations特性。我还没有找到很多关于它的精确GCC文档,但是让它运行是相当简单。

>首先使用-fprofile-generate编译程序。
>让程序运行(执行时间将显着更慢,因为代码也生成配置文件信息到.gcda文件)。
>使用-fprofile-use重新编译程序。如果你的应用程序是多线程的,还要添加-fprofile-correction标志。

PGO与GCC可以给出惊人的结果,真的显着提高性能(我看到一个15-20%的速度增加在我最近工作的项目之一)。显然,这里的问题是有一些数据足够代表你的应用程序的执行,这并不总是可用或容易获得。

GCC的并行模式

GCC具有并行模式,它是在GCC 4.2编译器出现的时候首次发布的。

基本上,它为您提供了C标准库中许多算法的并行实现。要在全局范围内启用它们,只需将-fopenmp和-D_GLIBCXX_PARALLEL标志添加到编译器。您还可以在需要时选择性地启用每个算法,但这将需要一些次要的代码更改。

有关此并行模式的所有信息,请参见here

如果您经常在大型数据结构上使用这些算法,并且有许多硬件线程上下文可用,这些并行实现可以提供巨大的性能提升。我只使用了并行执行排序到目前为止,但为了给出一个粗略的想法,我设法将我的应用程序中的排序时间从14到4秒(测试环境:1亿个对象与自定义比较器功能和8芯机)。

额外的技巧

与以前的点部分不同,此部分需要在代码中进行一些小的更改。它们也是GCC特定的(其中一些也在Clang上工作),因此编译时宏应该用于保持代码在其他编译器可移植。本节包含一些更高级的技术,如果你没有一些汇编级了解发生了什么,不应该使用。

> GCC内建,其列出为here.诸如__builtin_expect之类的构造可以帮助编译器通过提供分支预测信息来做更好的优化。其他构造如__builtin_prefetch在访问之前将数据带入高速缓存,并且可以帮助减少高速缓存未命中。
>功能属性,其中列出了here.特别是,你应该看看冷热属性;前者将向编译器指示该函数是程序的热点,并且更积极地优化该函数并将其放置在文本段的特殊子部分中,以获得更好的局部性;后者将优化函数的大小,并将其放置在文本部分的另一个特殊小节。

我希望这个答案将证明对一些开发人员有用,我会很高兴考虑任何编辑或建议。

http://stackoverflow.com/questions/14492436/g-optimization-beyond-o3-ofast

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:c-G优化超过-O3 / -Ofast