【发布时间】:2020-07-08 03:42:58
【问题描述】:
我有一个构建系统,它通过 -flto 标志使用 clang 中长期存在的 LTO 支持。
添加到 LLVM (https://clang.llvm.org/docs/ThinLTO.html) 的 ThinLTO 支持看起来很有趣,但我对在已经运行并发作业的构建系统的上下文中启动 std::thread::hardware_concurrency 并行处理线程的决定感到有些困惑。
如果您的构建系统已经为每个内核启动一个线程并运行编译和链接作业的混合,那么链接器假设它应该使用所有内核甚至多个内核仍然有意义吗?
或者使用https://clang.llvm.org/docs/ThinLTO.html#controlling-backend-parallelism 中记录的标志将 ThinLTO 后台并发减少到 1 是否有意义?删除并行性后,ThinLTO 与普通的普通旧 LTO 相比有什么优势吗?
【问题讨论】:
-
我的理解是它解决了构建过程的链接时间瓶颈。正如您所提到的,我的基于
ninja的翻译单元编译已经并行运行,但是链接步骤是分开的。在运行任何整个程序优化之前,将.o粘合在一起的瓶颈仍然存在于“传统”LTO 中。这就是解决规模和速度问题的主要优势之一。 -
@compor - 这对于您有大量先决条件编译然后最后一个最后链接步骤的链接是有意义的。但是如果你有很多编译和很多链接,比如单元测试二进制文件,那又如何呢?如果您正在与thinlto 并行运行这样的构建,在我看来,您最终可能会得到$NUMCPU 个并发链接,每个链接都使用$NUMCPU 个线程,这听起来像是大量的超额订阅。
-
这是有道理的,但是链接器适应这种情况有点困难(甚至超出范围?),因为我们正在讨论会产生不同二进制文件的不同调用(与 LTO 类型无关) .在这种情况下,我认为责任回到了构建工具,它为每个项目编排所有这些。
-
@compor - 当然,由构建系统进行调用,并且由于我认为超额订阅参数是有效的,所以我在构建中添加了必要的
'-Wl,-plugin-opt,jobs=1'咒语。但我真正好奇的是,这样做是否会完全降低-flto=thin相对于普通旧-flto的优势。或者,ThinLTO 是否做其他事情仍然使其成为在现代工具链中实现 LTO 的正确方法。如果它确实做了除了将并行性带到桌面之外的其他事情,那么这些事情是什么? ThinLTO 文档对此没有多说,而是专注于并发。 -
@compor - 一些进一步的想法。当我仔细研究 ThinLTO 设计时,似乎另一个方面是增量行为和缓存。这对于交互式使用来说听起来很有吸引力,所以在这种情况下使用thinlto 可能仍然有好处。但是对于每次提交都进行干净构建的 CI 系统,缓存可能没有用或不需要。那么我想知道,如果您同时考虑并行性和增量行为,那么
-flto=thin中是否还有比普通-flto更有价值的东西。研究还在继续……