/MP(使用多个进程生成)
/MP 选项在命令行上以减少总时间编译源文件。 /MP 选项使编译器创建一个或多个自身的副本,每个副本都位于单独的进程中。 然后这些副本同时编译源文件。 因此,可显著减少生成源文件的总时间。
/MP[processMax]
参数
processMax
(可选)编译器可创建的最大进程数。processMax 参数的范围必须为 1 到 65536。 否则,编译器发出警告消息 D9014,忽略 processMax 参数,并假设最大数目处理为 1。
如果您省略 processMax 参数,则编译器会从操作系统中检索您的计算机上的有效处理器的数目,然后为每个处理器创建一个进程。
备注
在您编译许多文件时,/MP 编译器选项可显著缩短生成时间。 为了提高生成时,编译器创建到 processMax 自身的副本,然后使用这些副本同时编译源文件。 /MP 选项适用于编译,但不适用于链接或链接时代码生成。 默认情况下 /MP 选项关闭。
生成时间的缩短取决于计算机上处理器的数目、要编译的文件数目以及系统资源的可用性,如 I/O 能力。 试用 /MP 选项以确定生成特定项目的最佳设置。 要获取可帮助您做出该决定的建议,请参见准则。
不兼容选项和语言功能
/MP 选项与一些编译器选项和语言功能不兼容。 如果您将不兼容的编译器选项与 /MP 选项一起使用,则编译器将发出警告 D9030,并忽略 /MP 选项。 如果使用不兼容的语言功能,编译器将发出错误 C2813然后结束或基于当前编译器警告等级选项继续。
备注
大多数选项是不兼容的,因为如果允许这些选项,则并发执行编译器会同时将其输出写入控制台或特定文件。因此,输出会混合在一起,产生混淆。在某些情况下,组合选项会使性能降低。
下表列出了与 /MP 选项不兼容的编译器选项和语言功能:
选项或语言功能 |
说明 |
---|---|
#import 预处理器指令 |
将类型库中的类型转换为 C++ 类,然后将这些类写入头文件。 |
将预处理器输出复制到标准输出 (stdout)。 |
|
启用增量重新生成。 |
|
将包含文件的列表写入标准错误 (stderr)。 |
|
编写预编译头文件。 |
诊断消息
如果您指定了与 /MP 选项不兼容的选项或语言功能,则您会收到一条诊断消息。 下表列出了消息和编译器行为:
诊断消息 |
说明 |
编译器行为 |
---|---|---|
C2813 |
#import 指令与 /MP 选项不兼容。 |
除非另外指定了编译器警告级别选项,否则编译终止。 |
D9014 |
为 processMax 参数指定的值无效。 |
编译器会忽略无效值,采用值 1。 |
D9030 |
指定的选项与 /MP 不兼容。 |
编译器会忽略 /MP 选项。 |
准则
测量性能
使用总生成时间来测量性能。 您可以使用物理时钟来测试生成时间,也可以使用计算生成开始和停止之间的时间差的软件。 如果您的计算机具有多个处理器,则物理时钟生成的结果可能比软件时间测量更准确。
有效处理器
计算机的每个物理处理器可具有一个或多个虚拟处理器,又称为有效处理器。 每个物理处理器可具有一个或多个核心,并且如果操作系统为核心启用了超线程,就类似于两个虚拟处理器。
例如,如果某计算机具有一个物理处理器,该物理处理器具有一个核心,并且禁用了超线程,则该计算机具有一个有效处理器。 与之相反,如果某计算机具有两个物理处理器,每个物理处理器具有两个核心,并且所有核心都启用了超线程,则该计算机具有八个有效处理器。 即,(8 个有效处理器)=(2 个物理处理器)x(2 个核心/物理处理器)x(2 个有效处理器/核心,由于超线程)。
如果您省略 /MP 选项中的 processMax 参数,则编译器会从操作系统中获取有效处理器的数目,然后为每个有效处理器创建一个进程。 但是,编译器无法保证特定处理器上执行的是哪个进程;这是由操作系统决定的。
进程数
编译器计算将用于编译源文件的进程数。 该值是您在命令行上指定的源文件数和您使用 /MP 选项显式或隐式指定的进程数中的较小者。 如果您提供了 /MP 选项的 processMax 参数,则可以显式设置进程的最大数目。 如果您省略了 processMax 参数,则可以使用默认值,该默认值等于计算机中的有效处理器的数目。
例如,假定您指定下面的命令行:
cl /MP7 a.cpp b.cpp c.cpp d.cpp e.cpp
在本例中,编译器使用了 5 个进程,因为它是 5 个源文件和最多 7 个进程中的较小者。 此外,假定您的计算机具有 2 个有效处理器,并且您指定了下面的命令行:
cl /MP a.cpp b.cpp c.cpp
在本例中,操作系统报告了 2 个处理器;因此,编译器在其计算中使用 2 个进程。 因此,编译器将使用 2 个进程执行生成操作,因为它是 2 个进程和 3 个源文件中的较小者。
源文件和生成顺序
可能无法按与源文件在命令行上的显示顺序相同的顺序来编译源文件。 虽然编译器创建了一组包含编译器副本的进程,但由操作系统安排每个进程的执行时间。 因此,无法保证按特定顺序编译源文件。
在有可用于编译源文件的进程时编译源文件。 如果文件多于进程,则可用进程会编译第一组文件。 当进程完成处理前一个文件,并可用于处理剩余文件之一时,将处理剩余文件。
不要在命令行上多次指定同一源文件。 例如,当某工具自动创建基于项目中的依赖项信息的生成文件时,可能会发生这种情况。 如果您未指定 /MP 选项,则编译器会按顺序处理文件的列表,并重新编译每个出现的文件。 但是,如果您指定 /MP 选项,则不同的编译器可能会同时编译同一文件。 因此,不同的编译器将尝试同时写入同一输出文件。 某个编译器将获取对输出文件的独占写权限并成功,而其他编译器将失败,出现文件访问错误。
使用类型库 (#import)
编译器不支持将 #import 指令与 /MP 开关一起使用。 如果可能,请按照下列步骤解决此问题:
将您的各种源文件中的所有 #import 指令移动到一个或多个文件,然后不使用 /MP 选项编译这些文件。 结果是一组生成的头文件。
在剩余的源文件中,插入指定生成的头的 #include 指令,然后通过使用 /MP 选项编译剩余的源文件。
Visual Studio 项目设置
MSBUILD.exe 工具
Visual Studio 使用 MSBuild.exe 工具来生成解决方案和项目。 MSBuild.exe 工具的 **/maxcpucount:**number (或 **/m:**number) 命令行选项可同时生成多个项目。 /MP 编译器选项可同时生成多个编译单元。 如果适用于您的应用程序,请通过使用 /MP 和/或 /maxcpucount 缩短您的解决方案的生成时间。
您的解决方案的生成时间在一定程度上取决于执行该生成操作的进程数。 MSBuild 选项的numbermaxcpucount 自变量指定了同时要生成项目的最大数量。 类似地,/MP 编译器选项的 processMax 参数指定同时生成的最大编译单元数。 如果 /maxcpucount 选项指定 P 个项目,/MP 选项指定 C 个进程,则最多可同时执行 P x C 个进程。
决定是使用 MSBuild 还是 /MP 技术的准则如下所示:
如果有许多项目,而每个项目中只有少数几个文件,请使用 MSBuild 工具。
如果有少数几个项目,而每个项目中有许多文件,请使用 /MP 选项。
如果项目数和每个项目中的文件数相当,请同时使用 MSBuild 和 /MP。 起初,将 /maxcpucount 选项设置为要生成的项目数,将 /MP 选项设置为您的计算机上的处理器数。 测量性能,然后调整设置以生成最佳结果。 重复此过程,直到您对总生成时间满意。
/Gm 编译器选项
默认情况下,项目生成会对调试版本启用 /Gm 编译器选项(增量生成),而对发布版本禁用该选项。 因此,在调试版本中会自动禁用 /MP 编译器选项,因为它与默认的 /Gm 编译器选项冲突。