GCC指南:关于安培处理器的CodesCode

学习如何有效使用GCC优化运行在Ampere处理器上的应用程序

本文最初由Ampere Computing发布。

本文介绍了如何有效地使用GNU编译器集合(GCC)选项来帮助优化Ampere处理器上的应用程序性能。

在优化应用程序时,测量潜在优化是否改善性能至关重要。这包括编译器选项。使用高级编译器选项可能会导致更好的运行时性能,但可能会增加编译时间、增加调试难度并且通常会增加二进制文件大小的成本。为什么编译器选项会影响性能超出了本文的范围,简短的回答是代码生成、现代处理器架构以及它们的相互作用都非常复杂!另一个重要的点是,由于计算机架构的差异和具体的微架构,不同的处理器可能受益于不同的编译器选项。对优化进行反复试验是取得性能成功的关键。

如何测量应用程序的性能以确定限制因素以及优化策略在先前发表的文章中已经涵盖过。文章Ampere Altra-Based实例上运行时的前10个问题描述了收集的性能数据以了解整个系统的性能。 一种用于优化Ampere Altra家族处理器的性能分析方法论解释了如何使用基于数据的方法高效有效地进行优化。

本文首先概述了最常见的GCC选项,以及这些选项如何影响应用程序。然后,讨论转向使用GCC选项来改善Ampere处理器上的VP9视频编码软件和MySQL数据库性能的案例研究。类似的策略已经成功地用于优化在Ampere处理器上运行的其他软件。

GCC建议

GCC编译器提供了许多可改善应用程序性能的选项。有关详细信息,请参阅GCC网站。为生成利用Ampere处理器中提供的所有性能功能的代码,请使用gcc -mcpu选项。

要使用gcc -mcpu选项,可以设置CPU模型或告诉GCC根据正在运行的机器使用CPU模型,例如-mcpu=native。注意,在遗留的基于x86的系统上,gcc -mcpu-mtune的不推荐代名词,而在Arm基于系统上,gcc -mcpu得到完全支持。详细信息,请参阅Arm的跨架构的编译器标志:-march,-mtune和-mcpu指南。

总之,尽可能只使用-mcpu,并在为Arm进行编译时避免使用-march-mtune。以下是通过设置gcc -mcpu选项来提高VP9视频编码软件性能的案例研究。

设置-mcpu选项:

  • -mcpu=ampere1:生成将在AmpereOne处理器上运行的代码。 AmpereOne是Ampere的下一代云原生处理器,将高性能处理器的系列扩展到具有新的行业领先核心数。注意,这可能会生成无法在Ampere Altra和Altra Max处理器上运行的代码。此选项最初在GCC版本12.1及更高版本中提供,然后被回溯到GCC 10.5和GCC 11.3。

  • -mcpu=neoverse-n1:生成将在Ampere Altra,Ampere Altra Max以及Ampere AmpereOne上运行的代码。虽然这个选项对于将在Ampere AmpereOne上运行的代码是支持的,但可能不会充分利用所有可用的新性能功能。注意,GCC版本需要9.1或更高版本才能启用针对Ampere Altra和Ampere Altra Max处理器的CPU特定调整。

  • -mcpu=native:生成根据GCC所运行的CPU设置CPU模型的代码。注意,GCC版本需要9.1或更高版本才能启用针对Ampere Altra和Ampere Altra Max处理器的CPU特定调整。

使用-mcpu = native 可能更容易使用,尽管如果可执行文件,共享库或对象文件在不同的系统上使用,则可能存在问题。如果构建是在Ampere AmpereOne处理器上完成的,则该代码可能无法在Ampere Altra或Altra Max处理器上运行,因为生成的代码可能包含Ampere AmpereOne处理器支持的Armv8.6+指令。 如果构建是在Ampere Altra或Altra Max处理器上完成的,则GCC将无法利用Ampere AmpereOne处理器上可用的最新性能改进。 这是在构建代码以利用任何体系结构的性能特性时的常见问题。

以下表列出支持Ampere Processor -mcpu 值的GCC版本。

处理器 -mcpu值 GCC 9 GCC 10 GCC 11 GCC 12 GCC 13
Ampere Altra neoverse-n1 ≥ 9.1 ALL ALL ALL ALL
Ampere Altra Max neoverse-n1 ≥ 9.1 ALL ALL ALL ALL
AmpereOne ampere1 N / A ≥ 10.5 ≥ 11.3 ≥ 12.1 ALL

我们建议使用适当的值(-mcpu = ampere1 -mcpu = neoverse-n1 -mcpu = native )与-O2 一起使用 gcc - mcpu 选项建立性能基准,然后探索其他优化选项并测量是否与基线相比改善了性能。

常见GCC选项摘要:

  • -mcpu 在构建Ampere处理器时建议使用,以启用处理器特定的调优和优化。 (有关详细信息,请参见上面的“设置-mcpu选项”部分的讨论。)

  • -Os 优化以减小代码大小,如果应用程序受到获取指令的限制,则可能这样做。

  • -O2 被认为是标准的GCC优化选项,并且与其他GCC选项进行比较时可作为基线使用。

  • -O3 添加了额外的优化以生成更有效的循环代码,如果您的应用程序性能主要由循环中花费的时间控制,则可以尝试。

  • 配置文件引导优化(PGO):– fprofile-generate 和 -fprofile-use。

  • 链接时间优化(LTO):-flto 。启用链接时间优化,允许编译器在各个源文件之间进行优化。这使得函数可以在源文件之间进行内联,除其他编译器优化之外。这也被认为是高级优化,并且可能需要对构建系统进行更改。此选项增加了总体构建时间,对于大型应用程序可能会产生很大的影响。可以仅对性能关键的源文件使用LTO,以可能减少构建时间。

gcc -mcpu 用于 VP9 视频编码案例研究

VP9 是由谷歌开发的视频编码格式。 libvpx 是谷歌和开放媒体联盟(AOMedia)为 VP8 和 VP9 视频编解码器提供的开源参考软件实现。相比 x264,libvpx 在视频压缩方面提供了显著的改进,但需要更多的计算时间。关于 VP9 和 libvpx 的更多信息,请访问 维基百科

在这个案例研究中,VP9 构建配置使用 gcc -mcpu=native 选项来提高性能。如上所述,当在 Ampere 处理器上编译时,使用 -mcpu 选项来启用特定 CPU 的调整和优化。最初采用默认配置构建 libvpx,然后再使用 -mcpu=native 进行重建。为评估 VP9 性能,使用了一个 1080P 的输入视频文件,来源于 YouTube 的 用户生成内容数据集 中的 original_videos_Sports_1080P_Sports_1080P-0063.mkv。有关如何为 Ampere 处理器构建 ffmpeg 和各种编解码器(包括 VP9)的详细信息,请参阅 Ampere 的 ffmpeg 调整和 构建指南

默认 libvpx 构建:

$ git clone https://chromium.googlesource.com/webm/libvpx$ cd libvpx/$ export CFLAGS="-mcpu=native -DNDEBUG -O3 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Wdeclaration-after-statement -Wdisabled-optimization -Wfloat-conversion -Wformat=2 -Wpointer-arith -Wtype-limits -Wcast-qual -Wvla -Wimplicit-function-declaration -Wmissing-declarations -Wmissing-prototypes -Wuninitialized -Wunused -Wextra -Wundef -Wframe-larger-than=52000 -std=gnu89"$ export CXXFLAGS="-mcpu=native -DNDEBUG -O3 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Wdisabled-optimization -Wextra-semi -Wfloat-conversion -Wformat=2 -Wpointer-arith -Wtype-limits -Wcast-qual -Wvla -Wmissing-declarations -Wuninitialized -Wunused -Wextra -Wno-psabi -Wc++14-extensions -Wc++17-extensions -Wc++20-extensions -std=gnu++11 -std=gnu++11"$ ./configure$ make verbose=1 $ ./vpxenc --codec=vp9 --profile=0 --height=1080 --width=1920 --fps=25/1 --limit=100 -o output.mkv /home/joneill/Videos/original_videos_Sports_1080P_Sports_1080P-0063.mkv --target-bitrate=2073600 --good --passes=1 --threads=1 –debug

如何使用 -mcpu=native 优化 libvpx 构建

$ # 重新使用 -mcpu=native 进行构建$ make clean$ export CFLAGS="-mcpu=native -DNDEBUG -O3 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Wdeclaration-after-statement -Wdisabled-optimization -Wfloat-conversion -Wformat=2 -Wpointer-arith -Wtype-limits -Wcast-qual -Wvla -Wimplicit-function-declaration -Wmissing-declarations -Wmissing-prototypes -Wuninitialized -Wunused -Wextra -Wundef -Wframe-larger-than=52000 -std=gnu89"$ export CXXFLAGS="-mcpu=native -DNDEBUG -O3 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Wdisabled-optimization -Wextra-semi -Wfloat-conversion -Wformat=2 -Wpointer-arith -Wtype-limits -Wcast-qual -Wvla -Wmissing-declarations -Wuninitialized -Wunused -Wextra -Wno-psabi -Wc++14-extensions -Wc++17-extensions -Wc++20-extensions -std=gnu++11 -std=gnu++11"$ ./configure $ make verbose=1 # 验证构建是否使用了 sdot 点积指令:$ objdump -d vpxenc | grep sdot | wc -l128$ ./vpxenc --codec=vp9 --profile=0 --height=1080 --width=1920 --fps=25/1 --limit=100 -o output.mkv /home/joneill/Videos/original_videos_Sports_1080P_Sports_1080P-0063.mkv --target-bitrate=2073600 --good --passes=1 --threads=1 --debug

使用Linux perf进行调查,以测量在函数中所花费的最多时间的CPU周期数,其中包括函数vpx_convolve8_horiz_neonvpx_convolve8_vert_neonlibvpx git仓库显示,这些函数经过Arm优化,使用Armv8.6-A USDOT(混合符号点积)指令,该指令由Ampere处理器支持。

使用gcc -mcpu=native在Ampere Altra处理器上启用点积优化,将vpx_convolve8_horiz_neon中花费的CPU周期从6.07E+11减少到2.52E+11,减少了2.4倍。

对于vpx_convolve8_vert_neon,CPU周期从2.46E+11降低到2.07E+11,降低了16%。

总体而言,使用-mcpu=native在Ampere Altra处理器上启用点积指令,通过提高应用程序吞吐量,将文件original_videos_Sports_1080P_Sports_1080P-0063.mkv的转码速度提高了7%。下表显示使用perf record和perf report工具收集的CPU周期和已退休指令数据。

构建配置 符号 周期百分比(%) 周期数 指令百分比(%) 指令数
默认构建 vpx_convolve8_horiz_neon 8.72 6.07E+11 7.52 1.13E+12
vpx_convolve8_vert_neon 3.53 2.46+E11 2.51 3.78E+11
全部应用程序 100 6.97E+10 100 1.48E+11
-mcpu=native vpx_convolve8_horiz_neon 3.89 2.52E+11 3.87 5.71E+11
vpx_convolve8_vert_neon 3.19 2.07+E11 3.29 4.86E+11
全部应用程序 100 6.48E+10 100 1.48E+11

GCC基于配置文件的优化

本节提供GCC的配置文件优化(PGO)概述以及使用PGO优化MySQL的案例研究。配置文件指南优化使GCC能够做出更好的优化决策,包括优化分支、代码块重排序、内联函数和循环优化,通过循环展开、循环剥离和向量化等方式。使用PGO需要修改构建环境以进行三部分构建。

  1. 使用配置文件指导优化,gcc -fprofile-generate构建应用程序。
  2. 在代表性工作负载上运行应用程序以生成配置文件数据。
  3. 使用配置文件数据重新构建应用程序,gcc -fprofile-use

使用PGO的挑战是步骤2中的极高性能开销。由于使用gcc -fprofile-generate构建的应用程序性能较慢,可能无法在运行中的生产环境系统上运行。请参阅GCC手册的程序仪表选项部分以构建具有运行时仪表的应用程序,以及控制优化的选项部分以重新使用生成的配置文件信息。

正如GCC手册所描述的那样,-fprofile-update=atomic 是多线程应用程序推荐的选项,可以通过收集改进的性能数据来提高性能。

何时使用PGO?

使用PGO,GCC可以通过提供额外的信息来更好地优化应用程序,例如测量分支的执行和未执行次数以及测量循环的迭代次数。PGO是一种有用的优化方法,可以尝试并查看是否改善了性能。使用PGO可以改善性能的性能特征包括具有大比例分支预测错误的应用程序,可以使用perf工具来读取CPU的性能监视单元(PMU)计数器BR_MIS_PRED_RETIRED进行测量。大量的分支预测错误导致高比例的前端停顿,可以使用STALL_FRONTEND PMU计数器进行测量。具有高L2指令缓存失效率的应用程序也可能从PGO中受益,可能与错误预测的分支有关。总结一下,大比例的分支预测错误、CPU前端停顿和L2指令缓存失效都是PGO可以改善性能的性能特征。

MySQL数据库GCC PGO案例研究

MySQL是全球最流行的开源数据库,由于MySQL二进制文件体积庞大,因此是使用GCC PGO优化的理想候选。在没有PGO信息的情况下,GCC无法正确预测执行的许多不同代码路径。使用PGO可以大大减少分支预测错误、L2指令缓存失效率和CPU前端停顿在Ampere Altra Max处理器上。

总结MySQL如何使用GCC PGO进行优化:

  1. 使用sysbench评估MySQL的性能
  2. 使用MySQL MTR(mysql-test-run)测试套件训练GCC PGO
  3. 使用Sysbench的oltp_point_selectoltp_read_only测试用例,比较PGO构建与默认构建的性能
  4. 然后改变所使用的线程数量从1到1024,平均速度提高了29%的oltp_point_select和20%的oltp_read_only测试,在Ampere Altra Max M128-30处理器上
  5. 64个线程下,PGO通过提高MySQL的吞吐量改善了32%的性能

更多详细信息可以在Ampere开发者网站的MySQL调优指南中找到。

总结

优化应用程序需要尝试不同的策略来确定哪种方法最有效。本文提供了使用不同GCC编译器优化生成在Ampere处理器上运行的高性能应用程序的建议。它强调使用-mcpu选项是生成利用Ampere Cloud Native Processors支持的所有特性的代码的最简单方式。MySQL数据库和VP9视频编码器的两个案例研究展示了使用GCC选项来优化这些对性能至关重要的应用程序。

作为可持续的云计算平台,Ampere的首款Cloud Native Processors为行业提供了前所未有的可预测高性能、平台可伸缩性和能效。我们邀请您在developer.amperecomputing.com上了解更多有关我们的开发者工作和最佳实践,并加入community.amperecomputing.com的讨论。

分享本文


Leave a Reply

Your email address will not be published. Required fields are marked *