哪些x86 C++编译器本身是多线程的?

12

现在几乎每个用户的桌面电脑(和大多数笔记本电脑)都拥有2或4个内核。高级用户使用amd或i7具备6-12个内核。

x86/x86_64 C/C++编译器中有哪些可以使用多线程进行编译?已经有类似于'make -j N'的解决方案,但是有时候(对于-fwhole-program-ipo),最后一步是巨大而缓慢的,并且是按顺序启动的。

以下哪些编译器可以:GCC、Intel C++ 编译器、Borland C++ 编译器、Open64、LLVM/GCC、LLVM/Clang、Sun 编译器、MSVC、OpenWatcom、Pathscale、PGI、TenDRA、Digital Mars?

对于多线程编译器,是否存在更高的线程数限制?

谢谢!

7个回答

5

Gcc提供了 -flto=n-flto=jobserver 选项,使得链接步骤(与LTO一起执行优化和代码生成)并行化。根据文档,这些选项自版本4.6起就已经可用,尽管我不确定早期版本的表现如何。


从哪个版本开始?有文档记录吗?如果确实如此[WHOPR!= LTO](https://gcc.gnu.org/onlinedocs/gccint/LTO-Overview.html),并且-flto可能比-flto = n具有更好(或仅仅是不同的)结果吗? - osgx
1
@osgx,我添加了一个文档链接。我不知道-flto-flto=42之间生成的代码有什么区别。 - Marc Glisse

4

一些构建系统可以并行编译独立的模块,但编译器本身仍然是单线程的。我不确定使编译器多线程化是否有任何好处。最耗时的编译阶段是处理所有 #include 依赖项,它们必须按顺序处理,因为各个头文件之间可能存在依赖关系。其他编译阶段严重依赖于先前阶段的输出,因此在那里几乎没有并行性的好处。


4
最耗时的是使用高级优化(O2、O3)和-ipo优化进行优化。 - osgx
2
代码生成和全局优化也需要很大一部分时间,并且它们可以并行处理。 - Yakov Galka
你不能用多线程程序建立一个线程安全的包含依赖项的队列吗? - Francisco Aguilera
“最耗时的编译阶段是处理所有的#include依赖关系”,你能支持这个说法吗(例如通过一些论文或基准测试)?根据我的经验,许多C++代码库都被模板重度代码所占据(源自Boost或其他地方)。 - yugr
其他编译阶段在很大程度上依赖于前一阶段的输出 - 但并非完全如此。例如,GCC LTO可以部分并行化编译过程。 - yugr

1
多线程编译并不是很有用,因为构建系统(如Make、Ninja)会同时启动多个编译单元。正如Ferrucio所说,同时编译真的很难实现。
然而,多线程链接可能是有用的(并发.o/.a读取和符号解析),因为这很可能是最后一个构建步骤。
GNU Gold链接器可以支持多线程,使用LLVM ThinLTO实现: https://clang.llvm.org/docs/ThinLTO.html

“多线程编译并不是真正有用的” - 如果您的编译时间由单个C++文件主导(我在开源软件和商业项目中都遇到过多次),或者在更改单个文件后进行增量构建时,它可能非常有用。并行编译已经在LLVM开发会议上讨论过,因此人们确实考虑过它。 - yugr
Gnu Gold链接器可以进行多线程处理。需要注意的是,Gold paper指出,多线程链接并没有提高链接速度。 - yugr
@yugr 主要的加速改进来自ThinLTO,正如我所说的那样。但是(我几个月前误读了),这种加速只针对非thin LTO。 - Salamandar

1
较新版本的Visual Studio可以并行编译不同的翻译单元。如果您的项目使用了许多实现文件(例如.c、.cc、.cpp),这将会很有帮助。 MSDN页面

这是指哪个版本的Visual C++编译器?我不知道项目内的并行编译是受支持的。 - Steve Townsend
2
这类似于“make -j N”的解决方案,因此它不是一个答案。 - osgx
VS 2008 和 2010 支持并行编译。请查看链接。 - watson1180
链接已检查。页面上写的是“进程”,而不是“线程”。此外,它将在不同的文件上进行并行工作。 - osgx
是的,只有在您的项目具有许多翻译单元时才有帮助。链接和更高级别的优化仍然是串行的。 - watson1180
但令人烦恼的是它无法执行nmake -j命令。有一个名为jom的线程化nmake替代工具,可以在http://qt.gitorious.org/qt-labs/jom找到。 - Martin Beckett

1

在链接阶段进行多进程处理并不是真正可行的。虽然可能存在一定程度的多线程处理,但这不太可能带来很大的性能提升。因此,许多构建系统将为不同的文件启动单独的进程。一旦它们都被编译完成,那么就会像你所说的那样执行一个长时间的单线程链接。遗憾的是,正如我所说的,你几乎无法对此做任何事情 :(


在大型项目中,当使用-O3甚至是-ipo-whole-program --combine模式时,链接阶段的时间相对较短。 - osgx
在MySQL中有一个文件,使用gcc编译可能需要数小时时间。这是一个SQL解析器,只有1 MB大小的单个文件。链接时间很短,但优化时间非常长。 - osgx
1
如果我没记错的话,Digitalmars C/C++编译器附带的链接器是多线程的(而且是用汇编语言编写的!),最终效果是成为世界上最快的链接器之一。它可能不会给出线性加速,但对于大型构建,它可能会节省几分钟的时间。 - BCS
Linux的gold链接器是多线程的(制作多线程链接器比制作多线程编译器要容易)。 - Basile Starynkevitch
1
@BasileStarynkevitch 注意,Gold的作者报告称多线程链接器没有加速。我很想知道是否有更多最新的基准测试... - yugr
显示剩余2条评论

1

Go 1.9编译器声称拥有:

并行编译

现在,Go编译器支持并行编译包的函数,利用多核优势。这是在go命令已经支持独立包的并行编译的基础上进行的。

但当然,它只编译Go,而不是C++。

我无法列举出任何在2017年10月以前也能做到这一点的C++编译器。但我猜想,多线程的Go编译器表明,多线程的C或C++编译器(原则上)是可能的。但是它们很少见,制作新的需要 巨大的工作, 你实际上需要从头开始进行这样的努力。


0

对于Visual C++,我不知道它是否进行任何并行编译(我认为不会)。对于Visual Studio 2005之后的版本(即Visual C++ 8),解决方案中的项目将尽可能地按照解决方案依赖关系图并行构建。


1
正如您所说,解决方案中的各个项目是并行编译的。单个项目在单个核心上单线程编译。链接步骤是单线程的。 - John Dibling

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