MSBuild - 如何并行构建多个文件和项目
MSBuild - How to build multiple files AND projects in parallel
我有一个很大的 Visual Studio 2010 解决方案文件 (.sln
),其中包含大量项目 (~50
)。每个项目大致由 20
.cpp
和 .h
个文件组成。在快速的 Intel i7 机器上构建整个项目大约需要 2 小时,所有依赖项都本地缓存在快速的 SSD 上。
我正在尝试 replicate an existing experiment I found on this topic,需要说明如何:
- 获取我正在寻求在 Visual Studio 中工作的并行化(使用 GUI/IDE)。
- 通过
MSBuild.exe
. 获取这些更改也适用于自动命令行构建
首先,/m
和/maxcpucount
选项一样吗?我有 read an article on the /m
option,,它似乎可以并行构建更多 项目 。这似乎与我在 GUI 中通过以下操作设置的选项相同:
- 工具
- 选项
- 项目和解决方案
- 构建和运行
Maximum number of parallel project builds
还有另一个选项,/MP
,我可以通过以下方式在 GUI 中访问:
- 项目
- 属性
- 配置属性
- C/C++
- 一般
Multi-processor Compilation
如果我在这方面有误请纠正我,但这似乎表明该项目将并行构建多个 .cpp
文件,但没有指定数量的选项,除非我必须手动在文本框中设置(即:/MP 4
或 /MP4
。
似乎为了让 /MP
工作,我需要禁用最小重建(即:Enabled Minimal Rebuild: No (/GM-)
),而且它也不适用于预编译的头文件。我已经解决了预编译头文件问题,方法是将预编译头文件设为解决方案首先构建的专用项目,然后再构建所有其他项目。
问题:如何通过命令行使用 MSBuild 为解决方案中的并行项目构建和并行文件 (.cpp
) 构建实施这些选项,并确认它们是否按预期工作?我上面的假设也正确吗? 我的最终目标是测试使用最多正在使用的内核总数构建项目,或者如果我的构建过程是 I/O 绑定而不是 CPU 绑定,甚至可能超载它。 我可以在 Linux 中通过以下方式轻松完成此操作:
NUMCPUS=`grep -c '^processor' /proc/cpuinfo`
NUMJOBS="$(echo "$NUMCPUS*1.5" | bc)"
NUMJOBS="$(printf '%.0f' $NUMJOBS)"
alias pmake='time nice make -j$NUMJOBS'
这允许我在我的 8 核 PC 上一次排队 12 个构建任务,并且 make
自动并行构建多达 12 个 .cpp
文件,处理隐式构建 rules/dependencies,等等。我试图在 Visual Studio Professional 和 MSBuild 中实现相同的目标。当我的构建受到 I/O 约束时,这种方法是保持所有内核处于 ~100%
使用率的最佳方法。
谢谢。
编译器 (cl.exe
) 的 /MP
开关和 msbuild.exe
的 /m
选项确实是可行的方法。以下是一些相关的 documentation 摘录:
The /MP option causes the compiler to create one or more copies of
itself, each in a separate process. Then these copies simultaneously
compile the source files. Optional Argument: The maximum number of
processes that the compiler can create. If you omit the processMax
argument, the compiler retrieves the number of effective processors on
your computer from the operating system, and creates a process for
each processor. The /MP option is incompatible with some compiler options and language features. If you use an incompatible compiler option with the /MP option, the compiler issues warning D9030 and ignores the /MP option
Examples suppose you specify the following command line:
cl /MP7 a.cpp b.cpp c.cpp d.cpp e.cpp
In this case the compiler uses five processes because that is the
lesser of five source files and a maximum of seven processes.
Alternatively, suppose your computer has two effective processors and
you specify the following command line:
cl /MP a.cpp b.cpp c.cpp
In this case the operating system reports two processors; therefore,
the compiler uses two processes in its calculation. As a result, the
compiler will execute the build with two processes because that is the
lesser of two processes and three source files.
所以正如您所注意到的,这都是关于编译器的,还没有关于 msbuild 的消息,因为编译器是一个独立的工具。换句话说:假设您打开 2 个命令 windows,并且在它们中同时调用 cl /MP3 a.cpp b.cpp c.cpp
之类的命令,您将同时拥有 6 个编译器进程 运行。哪个是您追求的行为,哪个也是 msbuild 可以做的。
调用 msbuild /?
的输出:
/maxcpucount[:n] Specifies the maximum number of concurrent processes
to build with. If the switch is not used, the default value used is 1.
If the switch is used without a value MSBuild will use up to the
number of processors on the computer. (Short form: /m[:n])
还有更多相关信息here,特别是它所说的部分
BuildInParallel is an optional boolean parameter on a MSBuild task.
When BuildInParallel is set to true (its default value), multiple
worker processes are generated to build as many projects at the same
time as possible. For this to work correctly, the /maxcpucount switch
must be set to a value greater than 1, and the system must be at least
dual-core or have two or more processors.
现在,如果您只是在一个典型项目上调用 msbuild /m my.vcxproj
,这不会做任何特别的事情,因为只有一个项目要构建。但是,如果在 msbuild 文件中有对 MsBuild 任务的调用,例如
<MsBuild Projects="@(ListOfProjects)" BuildInParallel="True"/>
和 /m 选项被传递给 msbuild,然后 msbuild 将根据上面列出的规则生成多个其他 msbuild 进程。巧合的是,这正是使用 msbuild 构建解决方案时发生的情况。 Msbuild 首先 converts the solution 到一个实际的 msbuild 文件,该文件使用解决方案中的项目列表调用 MsBuild 任务。因此,可以并行构建多个项目,并为此创建多个 msbuild 进程。反过来,如果这些是设置了 /MP 选项的 C++ 项目,则这些项目中的每一个都将创建多个编译器进程,从而产生最多 <max num cl processes> * <max num msbuild instances>
个并行编译。这取决于您的构建机器什么是最佳的,如果您愿意,您可以使用这些选项(为了有效地做到这一点,您的每个项目都将导入一个通用的 属性 sheet,您可以在其中设置 /MP选项,否则你必须单独编辑所有这些)并查看构建完成后 msbuild 报告的经过时间。我总是将 /m 和 /MP 的参数保留为默认值,因为我不希望使用我的项目的其他开发人员具有可能的次优配置,并且因为它很容易达到最大值 CPU.
您可以通过调用以下命令在命令行上实现此目的:
MSBuild /m:PARALLEL_PROJECT_COUNT /p:CL_MPCount=PARALLEL_FILE_COUNT
生成的进程数将为:
MSBuild = PARALLEL_PROJECT_COUNT
Cl = PARALLEL_PROJECT_COUNT * PARALLEL_FILE_COUNT
我有一个很大的 Visual Studio 2010 解决方案文件 (.sln
),其中包含大量项目 (~50
)。每个项目大致由 20
.cpp
和 .h
个文件组成。在快速的 Intel i7 机器上构建整个项目大约需要 2 小时,所有依赖项都本地缓存在快速的 SSD 上。
我正在尝试 replicate an existing experiment I found on this topic,需要说明如何:
- 获取我正在寻求在 Visual Studio 中工作的并行化(使用 GUI/IDE)。
- 通过
MSBuild.exe
. 获取这些更改也适用于自动命令行构建
首先,/m
和/maxcpucount
选项一样吗?我有 read an article on the /m
option,,它似乎可以并行构建更多 项目 。这似乎与我在 GUI 中通过以下操作设置的选项相同:
- 工具
- 选项
- 项目和解决方案
- 构建和运行
Maximum number of parallel project builds
还有另一个选项,/MP
,我可以通过以下方式在 GUI 中访问:
- 项目
- 属性
- 配置属性
- C/C++
- 一般
Multi-processor Compilation
如果我在这方面有误请纠正我,但这似乎表明该项目将并行构建多个 .cpp
文件,但没有指定数量的选项,除非我必须手动在文本框中设置(即:/MP 4
或 /MP4
。
似乎为了让 /MP
工作,我需要禁用最小重建(即:Enabled Minimal Rebuild: No (/GM-)
),而且它也不适用于预编译的头文件。我已经解决了预编译头文件问题,方法是将预编译头文件设为解决方案首先构建的专用项目,然后再构建所有其他项目。
问题:如何通过命令行使用 MSBuild 为解决方案中的并行项目构建和并行文件 (.cpp
) 构建实施这些选项,并确认它们是否按预期工作?我上面的假设也正确吗? 我的最终目标是测试使用最多正在使用的内核总数构建项目,或者如果我的构建过程是 I/O 绑定而不是 CPU 绑定,甚至可能超载它。 我可以在 Linux 中通过以下方式轻松完成此操作:
NUMCPUS=`grep -c '^processor' /proc/cpuinfo`
NUMJOBS="$(echo "$NUMCPUS*1.5" | bc)"
NUMJOBS="$(printf '%.0f' $NUMJOBS)"
alias pmake='time nice make -j$NUMJOBS'
这允许我在我的 8 核 PC 上一次排队 12 个构建任务,并且 make
自动并行构建多达 12 个 .cpp
文件,处理隐式构建 rules/dependencies,等等。我试图在 Visual Studio Professional 和 MSBuild 中实现相同的目标。当我的构建受到 I/O 约束时,这种方法是保持所有内核处于 ~100%
使用率的最佳方法。
谢谢。
编译器 (cl.exe
) 的 /MP
开关和 msbuild.exe
的 /m
选项确实是可行的方法。以下是一些相关的 documentation 摘录:
The /MP option causes the compiler to create one or more copies of itself, each in a separate process. Then these copies simultaneously compile the source files. Optional Argument: The maximum number of processes that the compiler can create. If you omit the processMax argument, the compiler retrieves the number of effective processors on your computer from the operating system, and creates a process for each processor. The /MP option is incompatible with some compiler options and language features. If you use an incompatible compiler option with the /MP option, the compiler issues warning D9030 and ignores the /MP option
Examples suppose you specify the following command line:
cl /MP7 a.cpp b.cpp c.cpp d.cpp e.cpp
In this case the compiler uses five processes because that is the lesser of five source files and a maximum of seven processes. Alternatively, suppose your computer has two effective processors and you specify the following command line:
cl /MP a.cpp b.cpp c.cpp
In this case the operating system reports two processors; therefore, the compiler uses two processes in its calculation. As a result, the compiler will execute the build with two processes because that is the lesser of two processes and three source files.
所以正如您所注意到的,这都是关于编译器的,还没有关于 msbuild 的消息,因为编译器是一个独立的工具。换句话说:假设您打开 2 个命令 windows,并且在它们中同时调用 cl /MP3 a.cpp b.cpp c.cpp
之类的命令,您将同时拥有 6 个编译器进程 运行。哪个是您追求的行为,哪个也是 msbuild 可以做的。
调用 msbuild /?
的输出:
/maxcpucount[:n] Specifies the maximum number of concurrent processes to build with. If the switch is not used, the default value used is 1. If the switch is used without a value MSBuild will use up to the number of processors on the computer. (Short form: /m[:n])
还有更多相关信息here,特别是它所说的部分
BuildInParallel is an optional boolean parameter on a MSBuild task. When BuildInParallel is set to true (its default value), multiple worker processes are generated to build as many projects at the same time as possible. For this to work correctly, the /maxcpucount switch must be set to a value greater than 1, and the system must be at least dual-core or have two or more processors.
现在,如果您只是在一个典型项目上调用 msbuild /m my.vcxproj
,这不会做任何特别的事情,因为只有一个项目要构建。但是,如果在 msbuild 文件中有对 MsBuild 任务的调用,例如
<MsBuild Projects="@(ListOfProjects)" BuildInParallel="True"/>
和 /m 选项被传递给 msbuild,然后 msbuild 将根据上面列出的规则生成多个其他 msbuild 进程。巧合的是,这正是使用 msbuild 构建解决方案时发生的情况。 Msbuild 首先 converts the solution 到一个实际的 msbuild 文件,该文件使用解决方案中的项目列表调用 MsBuild 任务。因此,可以并行构建多个项目,并为此创建多个 msbuild 进程。反过来,如果这些是设置了 /MP 选项的 C++ 项目,则这些项目中的每一个都将创建多个编译器进程,从而产生最多 <max num cl processes> * <max num msbuild instances>
个并行编译。这取决于您的构建机器什么是最佳的,如果您愿意,您可以使用这些选项(为了有效地做到这一点,您的每个项目都将导入一个通用的 属性 sheet,您可以在其中设置 /MP选项,否则你必须单独编辑所有这些)并查看构建完成后 msbuild 报告的经过时间。我总是将 /m 和 /MP 的参数保留为默认值,因为我不希望使用我的项目的其他开发人员具有可能的次优配置,并且因为它很容易达到最大值 CPU.
您可以通过调用以下命令在命令行上实现此目的:
MSBuild /m:PARALLEL_PROJECT_COUNT /p:CL_MPCount=PARALLEL_FILE_COUNT
生成的进程数将为:
MSBuild = PARALLEL_PROJECT_COUNT
Cl = PARALLEL_PROJECT_COUNT * PARALLEL_FILE_COUNT