LLVM的ThinLTO编译优化技术在Postgresql中的应用

部分内容引用:https://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html

LTO是什么?

链接时优化(Link-time optimization,简称LTO)是编译器在链接时对程序进行的一种优化。它适用于以文件为单位编译程序,然后将这些文件链接在一起的编程语言(如C和Fortran),而不是一次性编译(如Java的即时编译(JIT))。

传统上,编译器将所有文件分别编译成目标文件,然后将这些目标文件链接成一个单独的可执行文件。然而,在GNU编译器集合(GCC)和LLVM中实现的LTO中,编译器能够转储其中间表示(IR),即GIMPLE字节码或LLVM字节码,以便在最终链接时将组成单个可执行文件的所有不同编译单元作为单个模块进行优化。这扩大了跨过程优化的范围,涵盖了整个程序(或者更准确地说,链接时可见的所有内容)。通过链接时优化,编译器可以对整个程序应用各种形式的跨过程优化,进行更深入的分析、更多的优化,从而实现更好的程序性能。

实际上,LTO并不总是对整个程序进行优化,特别是动态链接的共享对象等库函数会被有意排除在外,以避免过多的重复和允许更新。静态链接自然适用于LTO的概念,但它只适用于包含IR对象而不是仅包含机器码的库存档文件。由于性能问题,甚至不总是直接使用整个单元,可以将程序分割成类似GCC的WHOPR的分而治之的LTO形式。当构建的程序本身是一个库时,优化会保留每个外部可用(导出的)符号,而不会过于努力地将它们作为DCE的一部分删除。

即使没有LTO,仍然可以使用一种更有限的WPO形式,例如GCC的-fwhole-program开关。这种模式使GCC假设正在编译的模块包含整个程序的入口点,因此其中的其他函数不会被外部使用,可以安全地进行优化。由于它仅适用于单个模块,因此无法真正涵盖整个程序。它可以与LTO结合使用,以一大模块的方式,这在链接器不会向GCC反馈外部使用的入口点或符号时非常有用。

LLVM提供的lto独立工具:

$ llvm-lto --help
OVERVIEW: llvm LTO linkerUSAGE: llvm-lto [options] <input bitcode files>OPTIONS:Color Options:--color                                 - Use colors in output (default=autodetect)Generic Options:--help                                  - Display available options (--help-hidden for more)--help-list                             - Display list of available options (--help-list-hidden for more)--version                               - Display the version of this programLTO Options:-O <char>                               - Optimization level. [-O0, -O1, -O2, or -O3] (default = '-O2')--check-for-objc                        - Only check if the module has objective-C defined in it--disable-verify                        - Do not run the verifier during the optimization pipeline--dso-symbol=<string>                   - Symbol to put in the symtab in the resulting dso--exported-symbol=<string>              - List of symbols to export from the resulting object file-j <uint>                               - Number of backend threads--list-dependent-libraries-only         - Instead of running LTO, list the dependent libraries in each IR file--list-symbols-only                     - Instead of running LTO, list the symbols in each IR file--lto-freestanding                      - Enable Freestanding (disable builtins / TLI) during LTO-o <filename>                           - Override output filename--print-macho-cpu-only                  - Instead of running LTO, print the mach-o cpu in each IR file--restore-linkage                       - Restore original linkage of globals prior to CodeGen--save-linked-module                    - Write linked LTO module to file before optimize--save-merged-module                    - Write merged LTO module to file before CodeGen--set-merged-module                     - Use the first input module as the merged module--thinlto                               - Only write combined global index for ThinLTO backends--thinlto-action=<value>                - Perform a single ThinLTO stage:=thinlink                             -   ThinLink: produces the index by linking only the summaries.=distributedindexes                   -   Produces individual indexes for distributed backends.=emitimports                          -   Emit imports files for distributed backends.=promote                              -   Perform pre-import promotion (requires -thinlto-index).=import                               -   Perform both promotion and cross-module importing (requires -thinlto-index).=internalize                          -   Perform internalization driven by -exported-symbol (requires -thinlto-index).=optimize                             -   Perform ThinLTO optimizations.=codegen                              -   CodeGen (expected to match llc)=run                                  -   Perform ThinLTO end-to-end--thinlto-cache-dir=<string>            - Enable ThinLTO caching.--thinlto-cache-entry-expiration=<uint> - Set ThinLTO cache entry expiration time.--thinlto-cache-max-size-bytes=<ulong>  - Set ThinLTO cache pruning directory maximum size in bytes.--thinlto-cache-max-size-files=<int>    - Set ThinLTO cache pruning directory maximum number of files.--thinlto-cache-pruning-interval=<int>  - Set ThinLTO cache pruning interval.--thinlto-index=<string>                - Provide the index produced by a ThinLink, required to perform the promotion and/or importing.--thinlto-index-stats                   - Print statistic for the index in every input files--thinlto-module-id=<string>            - For the module ID for the file to process, useful to match what is in the index.--thinlto-prefix-replace=<string>       - Control where files for distributed backends are created. Expects 'oldprefix;newprefix' and if path prefix of output file is oldprefix it will be replaced with newprefix.--thinlto-save-objects=<string>         - Save ThinLTO generated object files using filenames created in the given directory.--thinlto-save-temps=<string>           - Save ThinLTO temp files using filenames created by adding suffixes to the given file path prefix.--use-diagnostic-handler                - Use a diagnostic handler to test the handler interface

那么thinlto是什么?

LTO背景和动机

LTO(Link Time Optimization)是通过整个程序分析和跨模块优化来实现更好的运行时性能的一种方法。在编译阶段,clang会生成LLVM字节码而不是目标文件。链接器识别这些字节码文件,并在链接过程中调用LLVM来生成构成可执行文件的最终对象。LLVM实现会加载所有输入的字节码文件,并将它们合并成一个单独的模块。在这个庞大的模块上,进行了跨过程的分析(IPA)和跨过程的优化(IPO),这些优化是串行进行的。

在这里插入图片描述
在实践中,这意味着LTO通常需要大量的内存(一次性保存所有IR)并且非常慢。而且,如果通过-g启用了调试信息,IR的大小和所需的内存要求会显著增加。即使没有调试信息,这对于非常大的应用程序或在内存受限的机器上进行编译也是不可行的。这也使得增量构建变得不太有效,因为当任何输入源发生变化时,从LTO步骤开始的所有内容都必须重新执行。

ThinLTO是什么?

ThinLTO是一种新的方法,旨在像非LTO构建一样具有可扩展性,同时保留了完整LTO的大部分性能优势。

在ThinLTO中,串行步骤非常轻量且快速。这是因为它不是加载bitcode并合并单个庞大模块来执行这些分析,而是在串行链接步骤中利用每个模块的摘要进行全局分析,以及用于后续跨模块导入的函数位置索引。函数导入和其他IPO转换是在模块在完全并行的后端进行优化时执行的。

ThinLTO全局分析所启用的关键转换是函数导入,只有可能进行内联的函数被导入到每个模块中。这最大程度地减少了每个ThinLTO后端的内存开销,同时最大化了最有影响力的跨模块优化机会。因此,IPO转换是在每个扩展了其导入函数的模块上执行的。

ThinLTO过程分为3个阶段:

  1. 编译:生成带有模块摘要的IR,与完整LTO模式相同,
  2. Thin链接:thin链接器插件层,用于合并摘要并执行全局分析
  3. ThinLTO后端:基于摘要的导入和优化的并行后端(默认情况下,支持ThinLTO的链接器被设置为在线程中启动ThinLTO后端。因此,第二阶段和第三阶段之间的区别对用户来说是透明的)
    在这里插入图片描述

这个过程的关键是在第一阶段发出的摘要。

这些摘要使用位码格式发出,但设计得可以单独加载,而不涉及LLVMContext或任何其他昂贵的构造。每个全局变量和函数在模块摘要中都有一个条目。条目包含抽象描述该符号的元数据。例如,函数使用其链接类型、包含的指令数量和可选的分析信息(PGO)进行抽象化。此外,还记录了对其他全局变量的每个引用(地址引用、直接调用)。这些信息在Thin链接阶段期间构建了完整的引用图,并使用全局摘要信息进行快速分析。

总结:

ThinLTO的核心思想是将程序分为多个模块,每个模块都可以独立地进行编译和优化。然后,通过使用一个索引文件(称为"summary")来跟踪每个模块的信息,以便在链接阶段进行全局的优化。这种方式可以减少编译时间和内存消耗,同时仍能够实现类似于WPO的优化效果。

Postgresql中使用thinlto技术生成带有模块摘要的IR

PG根目录下的Makefile.golbal.in中增加了对LLVM的支持,位置:

# Install LLVM bitcode module (for JITing).
#
# The arguments are:
# $(1) name of the module (e.g. an extension's name or postgres for core code)
# $(2) source objects, with .o suffix
#
# The many INSTALL_DATA invocations aren't particularly fast, it'd be
# good if we could coalesce them, but I didn't find a good way.
#
# Note: blank line at end of macro is necessary to let it be used in foreach
define install_llvm_module
$(MKDIR_P) '$(DESTDIR)${bitcodedir}/$(1)'
$(MKDIR_P) $(sort $(dir $(addprefix '$(DESTDIR)${bitcodedir}'/$(1)/, $(2))))
$(foreach obj, ${2}, $(INSTALL_DATA) $(patsubst %.o,%.bc, $(obj)) '$(DESTDIR)${bitcodedir}'/$(1)/$(dir $(obj))
)
cd '$(DESTDIR)${bitcodedir}' && $(LLVM_BINPATH)/llvm-lto -thinlto -thinlto-action=thinlink -o $(1).index.bc $(addprefix $(1)/,$(patsubst %.o,%.bc, $(2)))endef

install_llvm_module函数中调用了llvm-lto -thinlto -thinlto-action=thinlink生成摘要文件:postgres.index.bc
在这里插入图片描述
postgres.index.bc只有2.7MB显然没有保存所有bitcode。通过llvm-dis反解成ll看下里面保存了什么:
在这里插入图片描述
在这里插入图片描述

  • 索引文件前半部分中保存了文件的bc路径、bc的moduleid。
  • 索引文件后半部分保存了全局变量、函数的信息,包括自身的全局guid、所属bc的moduleid、函数的连接类型、可见性、能否内联、能否抛出异常等等信息。

Postgresql如何加载使用postgres.index.bc

在llvm_load_summary中使用getModuleSummaryIndex加载postgres.index.bc,最后读取到defaultSearchPath中使用。

static std::unique_ptr<llvm::ModuleSummaryIndex>
llvm_load_summary(llvm::StringRef path)
{llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer> > MBOrErr =llvm::MemoryBuffer::getFile(path);if (std::error_code EC = MBOrErr.getError()){ilog(DEBUG1, "failed to open %s: %s", path.data(),EC.message().c_str());}else{llvm::MemoryBufferRef ref(*MBOrErr.get().get());llvm::Expected<std::unique_ptr<llvm::ModuleSummaryIndex> > IndexOrErr =llvm::getModuleSummaryIndex(ref);if (IndexOrErr)return std::move(IndexOrErr.get());elog(FATAL, "failed to load summary \"%s\": %s",path.data(),toString(IndexOrErr.takeError()).c_str());}return nullptr;
}

代码流程:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/671238.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Llama3-Tutorial之XTuner微调Llama3个人小助手

Llama3-Tutorial之XTuner微调Llama3个人小助手 使用XTuner微调llama3模型。 参考&#xff1a; https://github.com/SmartFlowAI/Llama3-Tutorial 1. web demo部署 参考上一节内容已经完成web demo部署&#xff0c;进行对话测试, 当前回答基于llama3官方发布的模型进行推理生成&…

项目|保障房房产管理系统,政务房产解决方案

一、系统概况 保障房管理系统是是为了落实中央关于住房保障的相关政策&#xff0c;实现对低收入家庭住房状况的调查管理、保障计划及落实管理、保障申请及审核管理、保障户和保障房源档案管理等。 针对政府保障房产管理的一站式解决方案&#xff0c;专注于为解决复杂、繁琐的…

为何美国多IP服务器搭建蜘蛛池SEO更经济?

为何美国多IP服务器搭建蜘蛛池SEO更经济? 随着网络时代的不断演进&#xff0c;搜索引擎优化(SEO)已经成为企业和个人提升网站曝光度的必经之路。在这个过程中&#xff0c;蜘蛛池(Spider Pool)服务被广泛应用。但是有趣的是&#xff0c;美国多IP服务器搭建蜘蛛池SEO服务却相对…

【学习AI-相关路程-工具使用-自我学习-cudavisco-开发工具尝试-基础样例 (2)】

【学习AI-相关路程-工具使用-自我学习-cuda&visco-开发工具尝试-基础样例 &#xff08;2&#xff09;】 1、前言2、环境说明3、总结说明4、工具安装0、验证cuda1、软件下载2、插件安装 5、软件设置与编程练习1、创建目录2、编译软件进入目录&创建两个文件3、编写配置文…

代码随想录算法训练营第三天 | 链表理论基础,203.移除链表元素,707.设计链表,206.反转链表

对于链表完全陌生&#xff0c;但是看题目又觉得和数组一样的 链表理论基础 Q&#xff1a;什么是链表&#xff1f; A&#xff1a;链表是由一系列结点组成的。每一个结点由两部分组成&#xff1a;数据和指针。 203.移除链表元素 题目&#xff1a; 给你一个链表的头节点 head 和…

【电影】【指环王】【中土世界】影碟播放记录

一、写在前面 笔者于5月5日&#xff08;昨天&#xff09;在新加坡淘到了一套《指环王 The Lord of the Rings》DVD光碟&#xff0c;今天却听闻噩耗&#xff0c;Rohan国王Theoden的扮演者&#xff0c;英国演员Bernard Hill去世&#xff08;享年79岁&#xff09;&#xff0c;发文…

从键入网址到网页显示,期间发生了什么?

从键入网址到网页显示&#xff0c;期间发生了什么&#xff1f; 孤单小弟【HTTP】真实地址查询【DNS】指南帮手【协议栈】可靠传输【TCP】远程定位【IP】两点传输【MAC】出口【网卡】送别者【交换机】出境大门【路由器】互相扒皮【服务器与客户端】相关问答 不少小伙伴在面试过程…

一竞技MSI:淘汰赛抽签结果出炉 BLG和T1同半区,TES首轮交手TL!

北京时间5月6日&#xff0c;MSI在今天进入短暂的休赛&#xff0c;在昨天结束的入围赛之后&#xff0c;PSG战队作为外卡赛区唯一的队伍进入到正赛&#xff0c;另外欧洲赛区的FNC战队也是击败GAM战队拿到正赛的资格。在比赛结束之后&#xff0c;也是进行了淘汰赛的胜败分组赛的抽…

GateWay检查接口耗时

添加gateway依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId> </dependency>创建一个LogTimeGateWayFilterFactory类&#xff0c;可以不是这个名字但是后面必须是x…

关于蓝队应急响应工具箱意见征集

前言 征集一下各位师傅的意见&#xff0c;没用过的师傅可以去以往的文章下载使用&#xff1a; 下载地址&#xff08;有个小小改动&#xff0c;去除了必要的python环境&#xff0c;使其占用空间更小&#xff09;&#xff1a; [护网必备]知攻善防实验室蓝队应急响应工具箱v202…

动态规划算法:路径问题

例题一 解法&#xff08;动态规划&#xff09;&#xff1a; 算法思路&#xff1a; 1. 状态表⽰&#xff1a; 对于这种「路径类」的问题&#xff0c;我们的状态表⽰⼀般有两种形式&#xff1a; i. 从 [i, j] 位置出发&#xff0c;巴拉巴拉&#xff1b; ii. 从起始位置出…

(读书笔记-大模型) LLM Powered Autonomous Agents

目录 智能体系统的概念 规划组件 记忆组件 工具组件 案例研究 智能体系统的概念 在大语言模型&#xff08;LLM&#xff09;赋能的自主智能体系统中&#xff0c;LLM 充当了智能体的大脑&#xff0c;其三个关键组件分别如下&#xff1a; 首先是规划&#xff0c;它又分为以下…