大多数答案都建议使用替代解决方案,例如不同的编译器或外部库,这很可能会带来大量的重写或集成工作。我将尝试坚持问题的实质,并按照OP的要求,通过激活编译器标志或对代码进行最少的更改来专注于单独使用GCC可以做什么。这不是一个“必须做的事情”的答案,而是更多的GCC调整的集合,这些调整对我来说效果很好,如果在您的特定情况下相关,您可以尝试一下。
有关原始问题的警告
在详细讨论之前,通常会给那些会问这个问题的人一些警告,阅读这些问题并说:“ OP正在优化O3之外,我应该使用与他相同的标志!”。
-march=native
支持使用特定于给定CPU架构的指令,而这些指令不一定在其他架构上可用。如果该程序在具有不同CPU的系统上运行,则可能根本无法运行,或者运行速度明显较慢(因为这也启用mtune=native
),因此,如果决定使用它,请注意这一点。更多信息在这里。
-Ofast
如您所述,启用了一些非标准的优化,因此也应谨慎使用。更多信息在这里。
其他GCC标志可试用
此处列出了不同标志的详细信息。
-Ofast
使-ffast-math
,这反过来又使-fno-math-errno
,-funsafe-math-optimizations
,-ffinite-math-only
,-fno-rounding-math
,-fno-signaling-nans
和-fcx-limited-range
。你可以去进一步浮点运算的优化选择地增加一些额外的标志,例如-fno-signed-zeros
,-fno-trapping-math
和其他人。这些不包括在-Ofast
并且可以使计算获得更多性能提升,但是您必须检查它们是否真正使您受益,并且不要中断任何计算。
- GCC还具有大量其他优化标记,而这些标记均未通过任何“ -O”选项启用。它们被列为“可能产生破损代码的实验选项”,因此,再次使用它们时应谨慎,并通过测试正确性和基准来检查其效果。不过,我经常使用
-frename-registers
,此选项从未对我产生过不想要的结果,并且往往会带来明显的性能提升(即可以在基准测试时进行测量)。但是,这是标志的类型,它非常取决于您的处理器。-funroll-loops
有时也会给出良好的结果(并暗示-frename-registers
),但这取决于您的实际代码。
PGO
GCC具有配置文件引导的优化功能。没有很多精确的GCC文档,但是运行它非常简单。
- 首先用
-fprofile-generate
。
- 让程序运行(由于代码还将生成配置文件信息生成到.gcda文件中,因此执行时间会明显变慢)。
- 重新编译程序
-fprofile-use
。如果您的应用程序是多线程的,还添加-fprofile-correction
标志。
带有GCC的PGO可以产生惊人的结果,并确实可以显着提高性能(我最近看到的一个项目的速度提高了15-20%)。显然,这里的问题是要有一些足够具有代表性的数据您的应用程序执行的数据,这些数据并不总是可用或容易获得。
GCC的并行模式
GCC具有Parallel Mode,该模式在GCC 4.2编译器退出时首次发布。
基本上,它为您提供了C ++标准库中许多算法的并行实现。要全局启用它们,您只需添加-fopenmp
和-D_GLIBCXX_PARALLEL
标志到编译器。您还可以在需要时有选择地启用每种算法,但这将需要一些小的代码更改。
有关此并行模式的所有信息都可以在此处找到。
如果您经常在大型数据结构上使用这些算法,并且有许多可用的硬件线程上下文,那么这些并行实现可以极大地提高性能。sort
到目前为止,我仅利用了并行实现,但是给出一个大概的想法,我设法将其中一个应用程序中的排序时间从14秒减少到4秒(测试环境:具有自定义比较器功能的1亿个对象的向量)和8核机器)。
额外的技巧
与前面的要点部分不同,此部分确实需要对代码进行一些小的更改。它们也是GCC特定的(其中一些也可以在Clang上工作),因此应使用编译时宏来使代码在其他编译器上可移植。本节包含一些更高级的技术,如果您对组装过程不了解,请不要使用本节。还要注意,处理器和编译器如今非常聪明,因此从此处描述的功能中获得任何明显的好处可能很棘手。
- GCC内置程序,在此处列出。这样的构造
__builtin_expect
可以通过为编译器提供分支预测信息来帮助其进行更好的优化。其他构造,例如__builtin_prefetch
在访问数据之前将其放入缓存,可以帮助减少缓存未命中。
- 函数属性,在此处列出。特别是,您应该研究
hot
和cold
属性;前者将向编译器指示该功能是程序的热点,并会更积极地优化该功能,并将其放置在text部分的特殊小节中,以实现更好的局部性;后者将优化功能的大小并将其放置在文本部分的另一个特殊子部分中。
我希望这个答案对某些开发人员有用,并且我很乐意考虑任何修改或建议。