关于链接时刻优化的看法
yingbo(五谷)
1. 静态链接程序的链接时刻优化。 已有的系统包括OM,ATOM&ALTO,DIABLO&FIT,CHARM&PIN,SPIKE。这类系统一般都包括两个部分: 1) 一个二进制插桩工具,用于对可执行程序进行剖视分析,比如ATOM,PIN等。 2) 一个二进制的优化系统,用于对可执行文件进行分析和优化,其输入和输出都是可执行文件,比如ALTO,DIABLO等。这个过程介于程序的在链接和运行之间,准确说这属于后链接时刻(post-link)优化。主要进行过程间分析和优化,包括过程间数据流分析,内联,常数传播,复制传播,公共子表达式消除,循环优化等等。 目前这些系统都大多是针对对静态链接的程序做优化。动态链接程序的难点在于程序中的重定位信息。PIN网站上说CHARM已经可以对动态链接的程序和动态库做优化,不过还有一些重定位类型不支持。 那么如何在链接时刻做优化呢,即linker工作的时候? 我曾经考虑过类似目前GCC中fprofile-arcs选项的功能(通过插桩使得程序在运行时生成描述函数控制流图特征的da文件,然后提供给编译器再次编译),让程序运行时提供文件间的关联信息,主要包括函数的调用图,使得链接器工作的时候利用这些信息来进行函数布局优化。 其它的优化就不见得比后链接时刻做有优势,毕竟链接时刻分析那么多的二进制文件还不如在最终生成的可执行程序上进行。所以在静态链接的程序上做也会容易一些,可以将库函数直接考虑进来。不过由于二进制文件缺少一些程序信息方面支持,有些优化做起来还是比较难。现在有很多的二进制翻译系统,可能也会提供一些idea上的帮助。 问题:链接器的输入一定要是二进制格式的.o文件吗? 2. 可以说JVM就是一个典型的链接时刻优化的例子。它提供给我们的思想就是:尽可能多保存程序原来的信息,和动态运行时刻做优化。 1)一种解决方法就是LLVM中使用的。 在GCC编译器中间加一层虚拟机,即GCC的过程变为Source_code --> RTL --> LLVA ISA(linktime and runtime optimization) --> Assembly。GCC的前端生成LLVA ISA表示的程序,然后在LLVM虚拟机上运行这种表达的程序,运行时刻得到更多程序的特征信息并生成优化的LLVA ISA表达,然后将其转换为目标机器上的指令。这被称为“next generation GCC”。这里使用的LLVA ISA是一种SSA表达的bytecode,主要是尽可能的保存源程序的信息。所以在一定的优化层次采用何种中间表达也是一个很值得考虑的问题。 从LLVM的结构看,这是一个程序全生命周期(编译,链接和运行三个时刻)的优化。这里的运行时刻避开了我们通常认为的可执行文件的运行时刻,而是通过一个中间层来“模拟”可执行文件真正的运行时刻,毕竟可执行文件运行时刻做优化比较难。至于为什么在那个虚拟层上运行程序,无非是为了得到辅助优化的程序特征信息。 2)另一种方法,我考虑是否能够扩展ELF格式来为优化提供更多的帮助,这种想法主要来源于调试器是利用ELF文件中一些特定的section来辅助调试,以及为了支持动态链接引入的.plt 和.got等section。 3. 无论如何,过程间分析与优化已经成为编译器中一个重要的优化,也是(后)链接时刻优化的一个重要基础。 GCC也正在实现这种优化,目前的做法是让编译器cc1接受多个源程序,并对参数中提供的多个源程序进行分析。比如, cc1 g2.c g3.c 这属于编译时刻进行过程间分析,相对于(后)链接时刻做过程间分析的优势就是可以看到更多源程序的信息。 我还不清楚产品级的编译器有没有这样做。微软的VC(7.0以上版本)基本采用了LLVM中那种思想,把代码生成推迟到链接时刻。当使用链接时刻优化时,编译器为每个文件生成一种中间格式(不清楚是什么格式,但不是.NET的bytecode),传递给链接器,链接器在这种格式上进行链接时刻优化(whole program optimizaon)并生成目标机器代码。这其实是一种很纯的链接时刻优化(对比前面的后链接优化而言)。这里也回答了1中提到的那个问题。 4. 考虑动态链接机制,减小符号解析和重定位的开销。 这是一篇比较动态和静态程序性能的论文中提到的。我个人感觉效果一般,只是一个小的点而已。还有,如果在运行时刻动态调整函数布局,权衡太多了,不如根据输入信息大体确定函数的运行特征,在链接时刻作一个“大概接近”的调整就行了。 5. 总之 1)函数重排是(后)链接范围内的事情。 2)在(后)链接时刻,一些经典的优化通过过程间分析来加强。内联非常重要,但是根据我已看的文献,内联比较难权衡!通过某种机制来加强已有的优化也是目前一个重要的方向! 3) 1 和 2都是很好的入手点。 4)通过扩展ELF格式也是一个可以去考虑的点。同样,类似LLVM和微软VC的方法也是可以尝试的,但这是极具challenging的。 5)至于动态链接程序的链接时刻优化,我很难逃离静态程序的链接时刻优化所作的事情去想出比较好的steps。或许这也正是难的地方。或者本来就是在whole program层次对一些经典优化的应用和加强,没什么新奇。 6)程序行为特征分析至关重要。不同应用中库函数的份量如何,或者建立程序性能特征库。从LLVM和微软VC中看,程序剖视信息是必需的。 7)裁减或更改库的结构,libc一定要那么大那么整合吗。能不能分开成libc1.so,libc2.so。。。这是函数布局的一个更纯粹做法,直接在库中就整合完。但是不同程序对库的需求不一样,还是难分离的。
你的回复
回复请先 登录 , 或 注册相关内容推荐
最新讨论 ( 更多 )
- 请问编译器方向的就业前景怎么样? (亮)
- 【招聘】编译器/虚拟机/EDA等领域的同学(华为2012社招/留学... (Alapha)
- 有哪些当前流行的语言是使用Flex+Bison开发的 (I)
- lex32 (老马在旁酒在手)
- 改进C语言?CWM, CS (老马在旁酒在手)