50

每次提交时,我都在 buildbot 中编译 2 个 C++ 项目。两者都是大约 1000 个文件,一个是 100 kloc,另一个是 170 kloc。从 gcc (4.4) 到 Visual C++ (2008) 的编译时间非常不同。

一个项目的 Visual C++ 编译需要 20 分钟。他们无法利用多个核心,因为一个项目依赖于另一个。最后,在 Debug 和 Release 中完整编译这两个项目(32 位和 64 位)需要超过 2 1/2 小时。

一个项目的 gcc 编译需要 4 分钟。它可以在 4 个内核上并行化,大约需要 1 分 10 秒。2 个项目的 4 个版本(调试/发布,32/64 位)的所有 8 个构建都在不到 10 分钟的时间内完成编译。

Visual C++ 编译时间发生了什么?它们基本上慢了 5 倍。

编译 C++ kloc 的平均预期时间是多少?我的是 7 s/kloc 和 vc++ 和 1.4 s/kloc 和 gcc。

可以做些什么来加快 Visual C++ 上的编译时间吗?

4

12 回答 12

17

减慢 VC++ 编译器的一件事是,如果您有一个头文件来初始化非平凡const值类型的具体实例。您可能会看到这种情况发生在类型常量std::string或 GUID 上。它会影响编译和链接时间。

对于单个 dll,这会导致 10 倍的减速。如果您将它们放在预编译的头文件中,或者只是在头文件中声明它们并在 cpp 文件中初始化它们,这会有所帮助。

请查看病毒扫描程序,并确保尝试使用预编译的标头,没有它您将看不到 VC++ 的最佳状态。

哦,是的,并确保 %TMP% 文件夹与您的构建写入的分区位于同一分区上,因为 VC++ 会生成临时文件并稍后移动它们。

于 2010-02-16T19:23:59.667 回答
10

相互依赖的项目并不意味着不可能进行并行化。构建系统足够聪明,可以找出并避免严重的依赖,否则 gcc 将无法使用 4 个内核。

所以(除了其他步骤),为什么不尝试在 Visual Studio 中使用 /MP 启用多处理(参见http://msdn.microsoft.com/en-us/library/bb385193.aspx)。

于 2010-02-12T11:38:29.990 回答
6

您如何构建 Visual Studio 项目?您是否只是在项目中运行 ide (devenv),/build或者您是否有一个类似于我假设您用于 gcc 的 makefile。我假设两个版本都使用类似的 makefile,但我认为值得检查。

您是否为任一编译器使用预编译头文件?如果您不使用 VS 的预编译头文件,那么您可能希望切换到使用它们。就我个人而言,我建议使用该#pragma hdrstop方法而不是单个全包头文件,但如果您当前没有使用预编译头文件并想尝试一个强制包含的单个全包头文件(使用/FI编译器命令行开关)无需任何代码更改即可快速测试。

我写了关于两者/FI#pragma hdrstop这里: http: //www.lenholgate.com/blog/2004/07/fi-stlport-precompiled-headers-warning-level-4-and-pragma-hdrstop.html

于 2010-02-12T12:08:16.950 回答
6

这不是问题的直接答案,但在我的公司,我们正在使用 IncrediBuild 进行分布式编译。它确实加快了编译过程。http://incredibuild.com/visual_studio.htm

于 2010-02-12T18:11:37.357 回答
3

John Lakos 所著的“大型 C++ 软件设计”一书提供了许多关于为大型项目构建代码和设计的技巧。包括许多加快编译速度的技巧。与 Visual C++ 没有直接关系,但无论如何都值得一读。

于 2010-08-05T11:50:46.190 回答
2

我写了两篇关于减少编译时间的技术的文章。在这些技术中,一篇关于预编译头文件统一构建的文章可能会帮助您缩短编译时间。他们附带了透明地处理技术的 CMake 脚本。

于 2010-02-21T19:02:52.867 回答
1

首先,在大多数情况下,您可以并行构建同一项目的调试和发布配置。

此外,您所描述的内容听起来非常慢 - 看起来您没有在 VC++ 中使用预编译头文件或错误地使用它们 - 它们专门用于缩短编译时间。

于 2010-02-12T11:22:15.483 回答
1

除非您强制完全重建,否则依赖项检查可能存在问题。

你可以制作一些静态库。将很少更改的代码放入库中。

构建程序最慢的部分:

  1. 打开和关闭文件。
  2. 解析和翻译源文件。

通常,链接和可执行文件创建阶段是最快的。

你确定:

  1. 哪个阶段最慢?
  2. 哪些文件编译速度最慢?

请记住,在确定效率时,请始终分析(以一种或另一种方式)。

于 2010-02-12T17:47:45.600 回答
0

你在同一台机器上构建吗?你用的是同一个操作系统吗?在比较 Cygwin 中的 GCC 和在托管 Cygwin 的 Windows 中运行的 VirtualBox 机器中的 GCC 时,我发现速度差异在 3-10 倍左右。

于 2010-02-12T11:37:58.120 回答
0

会有这样的差异似乎很奇怪……但是您也没有理由不能利用 Visual 上的多核!

基本上你有 4 种编译模式:(Debug/Release)x(32bits/64bits),每一种都是完全独立的,你可以完美地并行运行 4,充分利用可用的 4 个内核。或者简单地在 Visual Studio 上尝试 MultiProcessor 方法。

然而,这不会削减它。150 分钟与 10 分钟是一个巨大的差距。根据我的个人经验,减少编译时间有两个主要因素:

  • 在本地磁盘上使用所有文件(必要时使用远程复制)以及在本地创建的所有文件(.o .so)
  • 使用您可以使用的所有内核,如果可以的话,甚至可以使用 Multi Machines(distcc 等...)
于 2010-02-12T11:44:35.727 回答
0

一次编译和链接一个 cpp 文件,即使头文件更改会影响多个 cpp 文件。这可以通过视觉工作室宏来实现:

Dim WithEvents myTimer As Timers.Timer

Sub CompileAndLinkCurrentCppFile()
    DTE.ExecuteCommand("Build.Compile")
    myTimer = New Timers.Timer
    myTimer.Interval = 0.05
    myTimer.Start()
End Sub

Sub myTimer_Elapsed(ByVal ee As Object, ByVal dd As Timers.ElapsedEventArgs) Handles myTimer.Elapsed
    If DTE.Solution.SolutionBuild.BuildState <> vsBuildState.vsBuildStateInProgress And DTE.Solution.SolutionBuild.LastBuildInfo <> 1 Then
        myTimer.Stop()
        DTE.ExecuteCommand("Build.Link")
    End If
End Sub
于 2010-02-27T14:21:05.993 回答
0

不知道这是否仍然是一个问题以及您在开始时获得了多少改进,但是如果仍然存在 msbuild 不知道如何在一个项目中同时进行编排(每个 cpp 应该可以单独构建,除非您有一些 codegens - 代码生成器最好移到一个单独的项目中)你必须下载驱动程序开发工具包或 .NET SSCLI,因为它们都有 nmake,构建已知可以很好地并行化事情。SSCLI 已经有了构建构建设置,如果 DDK 有一些构建示例,请不要记住您是否必须从头开始。

还有一篇关于 MSBuild并行化的旧文章没有详细介绍,但提到了实际 msbuild 和 msbuild + sln 之间的一些差异。如果 /MP 与 /Gm 是唯一的问题,那么您可能需要编写一个小脚本或 C# exe 来编辑 .proj 文件以进行实验室构建。或者在项目中使用显式 cmd 行覆盖并从 env var 中获取该选项。

于 2010-10-25T01:33:17.180 回答