常熟高端网站建设,wordpress 多站,安徽网新科技有限公司网站开发,怎么做网站站内优化原文 使用LDC的(LTO)链接时优化的简短文章,包含演示了如何提高程序性能的简单示例.因为LTO在LLVMIR级别工作,因此可跨越C/D语言优化!
重要提示:LDC/LLVM的LTO在窗口上不可用.
链接时优化
(LTO)链接时优化是指链接时的程序优化.链接器提取所有目标文件在一起,并合并到一个程序…原文 使用LDC的(LTO)链接时优化的简短文章,包含演示了如何提高程序性能的简单示例.因为LTO在LLVMIR级别工作,因此可跨越C/D语言优化!
重要提示:LDC/LLVM的LTO在窗口上不可用.
链接时优化
(LTO)链接时优化是指链接时的程序优化.链接器提取所有目标文件在一起,并合并到一个程序中.链接器可看见整个程序,因此可分析和优化整个程序. 但是,一般链接器只有在程序已转换为机器码时才可见程序.在该级别上,应仍可优化,但这很难.不能使用GCC或LLVM的优化器.
与GCC相同,LLVM的LTO机制基于传递LLVM优化器可理解的(LLVMIR)代码给链接器,从而可在链接过程中执行全程序分析和优化.
所谓的完整LTO组合单独目标文件的所有LLVMIR代码到一个大的LLVM模块中,然后优化它并如常生成机器码. ThinLTO分开模块,但从其他模块按需导入函数,并并行优化和生成机器码.更多
可在一次编译调用中改进全LTO的所有优化,一次编译就可.一次编译所有是配音(dub),也是目前LDC自身(D部分)的构建方式.
LTO而不是一次编译的优点是,LTO的(部分)编译是并行完成的.对完整的LTO(-fltofull),只有语义分析是并行完成的,而优化和生成机器码是在单线程中完成的. 对ThinLTO(-fltothin),除全局分析步骤外,所有步骤都是并行完成的.因此,ThinLTO比全LTO或一次编译快得多,尤其是在拥有多个可用内核机器时.
要使用LTO,只需要在命令行上指定-fltothin或-fltofull!
链接器支持
LTO的工作方式是,编译器输出的目标文件不是普通目标文件:它们是LLVMIR位码文件,仅由目标文件扩展名伪装成目标文件.表明链接器必须支持此LLVM的LTO机制.
在MacOSX上,LLVM/Clang用作系统编译器,链接器知道如何用libLTO.DYLIB库处理LTO.适合MacOSX的LDC包附带此库,因此它是LDC的LLVM版本的最新版本.
在Linux上,黄金链接器支持插件,LLVM黄金插件用来处理LTO. 然后,可复制二进制文件到LDC的lib目录,或传递-flto-binarypluginfile给LDC,以便链接器可找到它. LTO选项(如增量构建的ThinLTO缓存)可像一般的链接器选项一样传递:
OS X: ldc2 -L-cache_path_lto -L/path/to/cache ...
gold: ldc2 -L-plugin-optcache-dir/path/to/cache ...简单示例
考虑以下示例,代码分布在(lto_a.d和lto_b.d)两个文件中:
// File lto_b.d
//用extern(C)来允许用C定义它
extern(C) void doesNothing() {}
// File lto_a.d
extern(C) void doesNothing(); //仅声明void main() {for (ulong i 0; i 1_000_000_000; i) {doesNothing();}
}先编译lto_b.d为lto_b.o,然后再编译lto_a.d,并与lto_b.o链接.该程序闲着,优化器应可弄清楚这一点,但是,优化器不能.编译lto_a.d时,它不知道Nothing()做了什么,因此不能做太多优化:程序循环1亿次调用立即返回的函数.在我机器上,大约需要2秒: ldc2 -c -O3 lto_b.d -oflto_b.oldc2 -O3 lto_a.d lto_b.o -ofprogramtime ./program
./program 1.81s user 0.01s system 98% cpu 1.845 total使用LTO,导入doesNothing()到lto_a模块中,优化器可发挥其神力: ldc2 -c -O3 -fltothin lto_b.d -oflto_b.oldc2 -O3 -fltothin lto_a.d lto_b.o -ofprogram_ltotime ./program_lto
./program_lto 0.00s 用户 0.00s 系统 28% CPU 总计 0.012 总计一次编译器调用中,编译所有源码可获得相同运行时: ldc2 -O3 lto_a.d lto_b.d -ofprogram_allatoncetime ./program_allatonce
./program_allatonce 0.00s user 0.00s system 44% cpu 0.008 total打破C/D语言障碍
D可(相对)轻松地与C代码互操作.LDC自身就是个很好示例:LDC的前端是用D编写的,而它的后端(LLVM)是用C编写的. 但是,不能一次编译所有源码来跨C/D语言优化,因为C和D的编译器都无法理解对方.因此,如下C函数不会内联到D函数中:
// File lto_b.cpp
void doesNothing() {}clang -c -O3 lto_b.cpp -o lto_b.oldc2 -O3 lto_a.d lto_b.o -ofprogram_cpptime ./program_cpp
./program_cpp 2.09s user 0.01s system 99% cpu 2.125 total好消息是:LTO没有语言障碍.因为LTO在LLVMIR级别工作,且LDC和Clang都编译为相同的LLVMIR语言,因此仅C,仅D和C/D混合程序可实现相同优化潜力!
对给定示例,可通过以下构建步骤减少执行时间到零: clang -c -O3 -fltothin lto_b.cpp -o lto_b.oldc2 -O3 -fltothin lto_a.d lto_b.o -ofprogram_cpp_lto -mtriplex86_64-apple-macosx10.11.0time ./program_cpp_lto
./program_cpp_lto 0.00s user 0.00s system 61% cpu 0.005 total注意,调用ldc2时,必须显式指定目标三元组(这仅在OSX上需要).在MacOSX上,LDC和Clang默认使用略有不同的三元组. 当三元组不同时,LTO代码生成器会抱怨.有趣的是,反向调用编译器时不需要显式提及三元组,但是必须显式传递D运行时库给Clang.