使用 Intel® C++ 编译器逐步优化性能。
使用 Intel® C++ 编译器逐步优化性能。
总的来说,使用 Intel® C++ 编译器进行性能优化有 6 个步骤。
1. 不带优化的编译
首先,这是入门的第一步。性能调优需要基于一个合格的应用程序。在开始性能调优之前,您需要确保应用程序的正确性。通常,我们在这一步使用 -O0 选项以便于调试。如果您的应用程序已经通过 GNU* 编译器或 Intel® C++ 编译器进行了验证,则可以开始下一步的性能调优。
2. 启用通用优化
在这一步,我们将启用最常见的编译器优化。您可以根据您的应用程序场景选择多种不同的选项。
-O1 和 -Os (Linux*) 或 /O1 和 /Os (Windows*)
此选项启用对速度的优化,并禁用一些会增加代码大小并影响速度的优化。为了限制代码大小,此选项启用了全局优化,包括数据流分析、代码迁移、强度降低和测试替换、分割生命周期分析和指令调度。此选项还禁用了一些内联函数的内联。如果指定了 -O1,则默认也会启用 -Os 选项,该选项侧重于不会增加代码大小的优化。使用 O1 选项时,编译器的自动向量化功能将禁用。
-O2 (Linux*) 或 /O2 (Windows*)
此选项启用对代码速度的优化。这是通常推荐的优化级别。编译器在 O2 及更高级别启用向量化。使用此选项,编译器将执行一些基本的循环优化、内联函数的内联、文件内过程间优化以及大多数常见的编译器优化技术。
-O3 (Linux*) 或 /O3 (Windows*)
执行 O2 优化,并启用更积极的循环转换,例如 Fusion(融合)、Block-Unroll-and-Jam(块展开和阻塞)以及 collapsing IF statements(折叠 IF 语句)。除非发生循环和内存访问转换,否则使用 O3 优化可能不会带来更高的性能。与 O2 优化相比,在某些情况下,这些优化可能会使代码变慢。O3 选项推荐用于包含大量浮点计算循环和处理大型数据集的应用程序。
-no-prec-div (Linux*) 或 /Qprec-div- (Windows*)
此选项将启用那些结果精度略低于完整 IEEE 除法的优化。在这种情况下,编译器可能会将浮点除法计算转换为乘以分母的倒数。例如,A/B 计算为 A * (1/B) 以提高计算速度。如果您的应用程序精度不如完整 IEEE 除法敏感,则可以启用此选项。
-ansi-alias (Linux*) 或 /Qansi-alias (Windows*)
此选项告诉编译器假定程序符合 ISO C 标准的别名规则。如果您的程序符合这些规则,则此选项允许编译器进行更积极的优化。如果不符合这些规则,则可能导致编译器生成错误的代码。仅当您的程序符合 ISO C 标准的别名规则时,才启用此选项。
此步骤的一个通用技巧是,您可以尝试使用 O2 和 O3 选项编译您的应用程序,并使用提供更高性能的选项。
3. 启用特定处理器优化
如果您的应用程序有特定的目标处理器,您可以使用选项 -x<code> (Linux*) 或 /Qx<code> (Windows*) 来启用特定处理器优化。此选项告诉编译器它可以针对哪些处理器特性,包括它可以生成的指令集和优化。它还启用了除 Intel® 特定功能优化之外的其他优化。
通过此选项生成的专用代码可能只能在 Intel® 处理器的一个子集上运行。使用这些选项代码值创建的可执行文件只能在支持指示的指令集的 Intel® 处理器上运行。由这些代码值生成的二进制文件将在支持指定功能的 Intel® 处理器上运行。
对于大多数嵌入式应用程序开发,由于目标处理器是固定的,您应该启用此选项以获得更高的性能。例如,如果您的嵌入式设备基于 Intel® Atom 处理器,并且您的应用程序将仅在该设备上运行,则可以启用 –xSSSE3_ATOM 选项以获得最佳性能。
对于基于 Intel Silvermont 的 Atom 处理器,您可以启用 -xATOM_SSE4.2 选项以获得 Silvermont 核心的优化。
在使用 Intel C++ 编译器针对 Quark SoC X1000 时,您可以利用以下两个编译器开关:
-mia32 告诉编译器为 IA-32 架构生成代码
-falign-stack=assume-4-byte 告诉编译器假设堆栈按 4 字节边界对齐。编译器可以在需要时动态将堆栈调整到 16 字节对齐。这将减小调用例程所需的数据大小。
您还可以参考以下链接,了解 -x 选项支持的 <code> 值的更多详细信息。
4. 使用 IPO 优化
过程间优化 (IPO) 是一个自动化的多步骤过程,它允许编译器分析您的代码,以确定可以受益于特定优化的位置。使用 IPO 选项,您可能会看到针对 Intel 微处理器比针对非 Intel 微处理器更多的优化。
在启用 IPO 优化之前,您必须将原始的归档器“ar”和链接器“ld”更改为 Intel® 的“xiar”和“xild”。有关如何从 GNU* 编译器移植到 Intel® C++ 编译器的更多详细信息,请参阅以下文章。
http://software.intel.com/en-us/articles/using-intel-c-compiler-for-embedded-system
IPO 是一种跨文件优化。通常,您可以通过“-ipo”选项启用 IPO 优化。通过此选项,编译器将在生成的对象文件中添加一些中间数据。在链接阶段,会调用编译器,根据对象文件中的中间数据执行多文件优化。IPO 优化可以进行多种优化。
启用 IPO 优化会增加内存需求,并延长编译时间。特别是对于非常大的应用程序,您可能会发现编译时间显著增加。
有关 IPO 优化的更多详细信息,请参阅《Intel® C++ 编译器用户和参考指南》> 主要功能 > 过程间优化 (IPO)。
5. 使用 PGO 优化
面向配置文件的优化 (PGO) 通过重新组织代码布局来减少指令缓存问题、减小代码大小和减少分支预测错误来提高应用程序性能。PGO 向编译器提供有关应用程序最常执行区域的信息。通过了解这些区域,编译器可以更有选择性和更具体地优化应用程序。
PGO 由三个阶段或步骤组成。
第一步是检测程序。在此阶段,编译器从您的源代码和编译器的特殊代码中创建并链接一个检测过的程序。在此步骤中,您需要启用“-prof-gen”选项,让编译器生成检测过的二进制文件。
第二步是运行检测过的可执行文件。每次执行检测过的代码时,检测过的程序都会生成一个动态信息文件,该文件用于最终编译。
第三步是最终编译。第二次编译时,会将动态信息文件合并为一个摘要文件。使用该文件中的配置文件摘要,编译器会尝试优化程序中最常执行路径的执行。在此步骤中,您需要启用“-prof-use”选项,让编译器使用在第二步中生成的配置文件。
对于嵌入式开发,您可能需要使用“-prof-dir=<val>”选项来指定执行期间生成配置文件的路径。请注意,“<val>”是目标系统中的文件夹名称。程序退出后,您将在该文件夹中找到生成的配置文件。
您需要将目标系统中生成的配置文件(.dyn 文件)复制到您的主机,将其放在主机上的一个文件夹中,然后更改 -prof-dir 选项的值以指定存储配置文件的主机文件夹。
以下是为嵌入式系统启用 PGO 优化所需执行的基本步骤:
1. 启用 -prof-gen 选项和 -prof-dir=<val> 选项,其中 <val> 代表目标计算机上的文件夹名称。
2. 编译完成后,在目标计算机上运行您的程序。在 -prof-dir 指定的文件夹中找到 .dyn 文件,将 .dyn 文件复制到主机。
3. 将 -prof-gen 选项更改为 –prof-use,将 –prof-dir 选项的值更改为指定主机上存储配置文件的文件夹,然后重新编译应用程序。
您需要确保您的程序能够退出,以便生成配置文件。在嵌入式系统中,如果您的程序无限期运行而没有退出点,您需要做一些额外的工作来确保可以生成配置文件。
1. 在程序中手动添加退出代码。
2. 在源文件中添加 PGO API _PGOPTI_Prof_Dump_All() 来转储配置文件。
3. 使用环境定期转储,例如,使用以下环境变量每 5000 微秒将所有内容转储到一个文件中:
export INTEL_PROF_DUMP_INTERVAL 5000
export INTEL_PROF_DUMP_CUMULATIVE 1
有关 PGO 优化的更多详细信息,请参阅《Intel® C++ 编译器用户和参考指南》> 主要功能 > 面向配置文件的优化 (PGO)。
6. 调整自动向量化
自动向量化器(也称为 auto-vectorizer)是 Intel® 编译器的一个组件,它会自动使用 Intel® Streaming SIMD Extensions(Intel® SSE、SSE2、SSE3 和 SSE4 向量化编译器和媒体加速器)以及 Supplemental Streaming SIMD Extensions(SSSE3)指令集和 Intel® Advanced Vector Extension 指令集中的 SIMD 指令。向量化器检测程序中可以并行执行的操作,并将顺序操作转换为并行操作;例如,向量化器将处理 2、4、8 或最多 16 个元素的顺序 SIMD 指令转换为并行操作,具体取决于数据类型。
对于包含大量数据处理循环的大多数数据处理应用程序来说,编译器向量化是一个关键点。编译器还提供了详细的报告,帮助您了解哪些循环被向量化,哪些循环未被向量化以及原因。有一篇在线白皮书可以帮助您理解编译器自动向量化功能并帮助您编写可向量化的循环。有关更多详细信息,请参阅以下链接:
http://software.intel.com/sites/default/files/m/4/8/8/2/a/31848-CompilerAutovectorizationGuide.pdf
摘要
根据以上步骤,我们可能有以下 Intel® C++ 编译器选项(Linux*),可以轻松应用于您的应用程序以获得高性能。
-O2/O3 -no-prec-div -x<code> -ipo -prof-gen/-prof-use -prof-dir=<val>
Intel® C++ 编译器提供了许多高级和特定功能供您调优应用程序性能。本文所述的步骤适用于大多数应用程序。还有许多其他编译器选项可能有助于您进行细粒度性能优化。有关更多详细信息,请参阅 Intel® C++ 编译器用户和参考指南。
您还可以使用 Intel® Vtune Amplifier 来调查应用程序的性能热点和架构性能问题。Intel Vtune Amplifier 是一个高度推荐的性能分析和性能调优工具。