icc的过程间优化和性能分析引导优化

icc(Intel C++ Compiler)是一个非常厉害的编译器,对优化计算密集型的程序远超其他任何编译器,如gcc、llvm、Visual C++。

icc提供了过程间优化(Interprocedural Optimization)技术,可以帮助编译器在不同的目标文件之间进行全局优化。传统的编译器的编译过程是编译每个源文件到独立的目标文件,然后再通过链接器将目标文件链接成可执行文件。传统的编译器的编译优化主要集中在每个源文件内部,链接过程比较简单,因此每个文件都是独立的,而icc提供的过程间优化打破了这一限制。

过程间优化可以对整个程序进行全局优化,而不是仅仅在单个文件、单个函数或者单个代码块内部优化。过程间优化可以减少过程之间重复计算、内存的低效访问以及简化迭代过程,通常会采用内联函数的方式。过程间优化还可以重排代码的顺序以优化内存的分配方式和局部性。

通过指定编译参数-ipo,icc可以开启过程间优化,icc将在编译时生成特殊格式的目标文件(中间语言),并在链接时进行进一步的编译和过程间优化,如图所示:

使用icc启动过程间优化的方式是在编译参数中加上-ipo参数,还要设置环境变量AR=xiar,使用Intel的版本代替默认的ar

性能分析引导优化(Profile Guided Optimization)通过分析程序运行时的实际行为,将结果反馈给编译器,使得编译器可以重新安排代码以减少指令缓存问题和分支预测误判,从而获得性能的提升。性能分析引导优化通过实际执行代码统计出运行频率最高的部分,编译器通过这些信息可以更加针对地优化代码。性能分析引导优化分为三个阶段:

  1. 第一步是生成分析程序。在这个阶段,编译器创建一个有采样注入的可执行程序。在icc中使用的编译指令是-prog-gen,以及-prof-dir=[dir]
  2. 第二步是运行第一步生成的被注入采样分析的程序,每次运行这个程序,都会生成-prof-dir指定的目录下生成一个动态信息文件(dynamic information file),将会被最终编译时使用。
  3. 第三步是最终编译的步骤。第二次编译的时候,动态信息文件会合并成一个汇总文件。通过汇总文件,编译器会尝试将最常使用的执行路径优化。

过程间优化和性能分析引导优化可能会相互影响,性能分析引导优化通常会帮助编译器生成内联函数,这会帮助过程间优化的效率。性能分析引导优化对分支预测效率的提升最有效果,许多分支执行的可能性无法在编译时判断,而通过性能分析引导优化,编译器可以针对经常执行的分支(热代码)和不经常执行的分支(冷代码)生成高效的汇编代码。

使用性能分析引导优化的方法如下:

  • 第一阶段:编译参数中加上:-prof-gen=srcpos -prof-dir=/tmp/profdata。其中-prof-dir是存储性能分析文件的目录。
  • 第二阶段:运行编译好的程序,然后运行profmerge -prof_dir /tmp/profdata生成汇总文件。
  • 第三阶段:重新编译程序,使用参数:-prof-use=nomerge -prof-func-groups -prof-dir=/tmp/profdata

这样最终生成的代码就是经过性能分析优化过后的了。

以上方法在icc 14.0.2上试验通过。

参考

相关日志