GCC LTO:限制优化范围

6
一个相当大的共享库(许多模板实例化)的一个 LTO 构建需要相当长的时间(>10 分钟)。现在我了解一些关于该库的信息,并且可以指定某种“黑名单”,以对象文件的形式表示,这些文件 不需要 被一起分析(因为它们之间没有应被内联或其他调用),或者我可以指定应当一起分析的对象文件组。是否有可能在不分割库的情况下实现这一点?

你可以在开发时不使用 LTO,只有在发布候选版本时才打开它。 - Galik
分析和解决性能问题时,重复进行本地构建也是必要的。 - Martin Richtarsky
我不确定你能获得多少胜利。你尝试过使用-flto=8(或任何数字或-flto=jobserver)来获取一些并行性吗? - Marc Glisse
我已经在使用-flto=40了 :) LTO的操作在这里有描述: https://gcc.gnu.org/onlinedocs/gccint/LTO-Overview.html 它分为三个阶段:LGEN、WPA和LTRANS。WPA对代码进行分区,然后LTRANS并行运行在这些分区上。我可以看到在LTRANS阶段大约有15个线程在运行,但应该还有更多。我需要明确指导WPA的分区以改变这种情况。 - Martin Richtarsky
3个回答

5
有一个很少使用的ld功能,叫做-r/--relocatable,可以用来将多个目标文件合并成一个,然后再链接到最终产品中。如果在这里实现LTO(链接时优化),而后面没有实现,那么你就可以得到所需的“部分”LTO。
遗憾的是,ld -r不起作用;它只是将所有的LTO信息组合起来,以便稍后处理。但是通过gcc驱动程序调用它(gcc -r)似乎可以工作。

a.c

int a() {
    return 42;
}

b.c

int a(void);

int b() {
    return a();
}

c.c

int b(void);

int c() {
    return b();
}

d.c

int c(void);

int main() {
    return c();
}
$ gcc -O3 -flto -c [a-d].c
$ gcc -O3 -r -nostdlib a.o b.o -o g1.o
$ gcc -O3 -r -nostdlib c.o d.o -o g2.o
$ gcc -O3 -fno-lto g1.o g2.o
$ objdump -d a.out
...
00000000000004f0 <main>:
 4f0:   e9 1b 01 00 00          jmpq   610 <b>
...
0000000000000610 <b>:
 610:   b8 2a 00 00 00          mov    $0x2a,%eax
 615:   c3                      retq   
...

所以main()被优化为return b();,而b()被优化为return 42;,但是这两组之间没有进行过程序间优化。


谢谢您发布这个。我也已经更新了我的答案。 - Hadi Brais

3
假设你想将a.cb.c组合成一组进行优化,将c.cd.c组合成另一组。你可以使用以下方式使用-combine GCC开关:
$ gcc -O3 -c -combine a.c b.c -o group1.o
$ gcc -O3 -c -combine c.c d.c -o group2.o

请注意,您不需要使用LTO,因为-combine开关会在优化代码之前合并多个源代码文件。
编辑:
目前,-combine仅支持C代码。实现此操作的替代方法是使用#include指令,如下所示:
// file group1.cpp
#include "a.cpp"
#include "b.cpp"

// file group2.cpp
#include "c.cpp"
#include "d.cpp"

然后,它们可以按照以下方式编译,而无需使用LTO:

g++ -O3 group1.cpp group2.cpp

这实际上是模拟分组或部分LTO。

然而,尚不清楚这种技术或另一个答案中提出的技术哪个编译速度更快。此外,代码可能没有以完全相同的方式进行优化。因此,应该比较使用每种技术产生的代码的性能。然后可以使用首选技术。


1
谢谢您的建议。据我所知,combine仅适用于C代码,而不适用于C ++。 - Martin Richtarsky
1
ld -r 可以与 LTO 一起使用,但并非 OP 想要的方式。它似乎只是将 LTO 信息连接在一起,最终链接器仍会对整个程序进行 LTO。另一方面,gcc -r -nostdlib 貌似可以满足 OP 的需求。 - Tavian Barnes
@TavianBarnes gcc -r -nostdlib 是什么意思?它会生成本地目标文件吗?它能与 LTO 一起使用吗? - Hadi Brais
@TavianBarnes,你的意思是说gcc -r会对所有输入源文件进行LTO优化,并生成一个优化后的本地目标文件?因为这正是OP所需要的。 - Hadi Brais
1
@HadiBrais 感谢您的回答。我认为这个原则上是可行的,但我担心当编译一些源文件时会出现问题。但如果 gcc -r 无法工作,这将是一个替代方案。 - Martin Richtarsky
显示剩余4条评论

0

您可以通过不使用-flto选项来完全排除目标文件参与链接时优化的过程。


我不想完全排除文件,我只想通过注释来指导优化器,比如“一起优化这些目标文件”。 - Martin Richtarsky
据我所知,你不能这样做。你要么使用带有LTO结构的对象文件(即一些gcc字节码)以及常规机器代码,要么不使用它们。 - flapenguin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接