【问题标题】:How do I configure portable parallel builds in CMake?如何在 CMake 中配置可移植并行构建?
【发布时间】:2012-05-28 03:33:28
【问题描述】:

无论使用哪种构建工具,是否有可能进行并行构建?

在 Unix 下我们可以添加 make -jN 其中 N 是线程数,在 Windows 下我添加到 CXX_FLAG "/MP" 然后在 Visual Studio 中用于并行构建...(?)我怎样才能让我的当我运行 CMake 时,CMAKE_MAKE_PROGRAM 并不总是扩展的版本?

什么是通用解决方案?

我想出了这个:

# Add some multithreaded build support
MARK_AS_ADVANCED(MULTITHREADED_BUILD)
set(MULTITHREADED_BUILD 12 CACHE STRING "How many threads are used to build the project")
if(MULTITHREADED_BUILD)
    if(${CMAKE_GENERATOR} MATCHES "Unix Makefiles")
            message(STATUS ${CMAKE_BUILD_TOOL})
            set(CMAKE_MAKE_PROGRAM "${CMAKE_MAKE_PROGRAM} -j${MULTITHREADED_BUILD}")
            message(STATUS "Added arguments to CMAKE_BUILD_TOOL: ${CMAKE_MAKE_PROGRAM}")
    elseif(MSVC)
      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
      message(STATUS "Added parallel build arguments to CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
    endif()
endif()

【问题讨论】:

  • 不确定能不能做到,反正也不是什么好主意。 CMake 描述了项目是如何构建的,make 是如何做的,这与 CMake 不同。
  • 扩展您的方法只需在 cmake 的命令行中添加 -DMULTITHREADED_BUILD=12。并删除SET(MULTITHREADED_BUILD ...)
  • 在我的情况下,Eclipse CDT 导致错误:“/usr/bin/make -j8”全部无法运行程序“/usr/bin/make -j8”:未知原因错误:程序“/在 PATH 中找不到 usr/bin/make -j8"
  • 我的 CMake / Eclipse CDT 错误是由于 CMAKE_MAKE_PROGRAM 错误:cmake.org/Bug/view.php?id=15497
  • 由于这个帖子有点老了,CMake >= 3.12.0 的用户应该考虑@usr1234567 的回答

标签: cmake parallel-builds


【解决方案1】:

使用 CMake 3.12,这是可能的。来自release notes

cmake(1) 构建项目 (cmake --build) 获得了 --parallel [<jobs>]-j [<jobs>] 选项来指定并行构建级别。它们映射到本机构建工具的相应选项。

As mentioned by dkg,也可以设置环境变量CMAKE_BUILD_PARALLEL_LEVEL

CMake 文档的链接:

【讨论】:

  • 你也可以设置环境变量CMAKE_BUILD_PARALLEL_LEVEL
  • “它们映射到本机构建工具的相应选项”究竟是什么意思?例如,在使用 CMake 3.16.4 和 Ninja 1.10.0 时,它似乎不会自动为 MSVC 设置 /MP 标志。因此,对于真正/完全并行的构建,似乎仍然没有可用的跨平台解决方案。
【解决方案2】:

如果您有 CMake v2.8.8 或更高版本,您可以使用 Ninja 替代 GNU make

mkdir build
cd    build
cmake -G Ninja ..
ninja              # Parallel build (no need -j12)

mkdir build
cd    build
cmake -G Ninja ..
cmake --build .    # Parallel build using Ninja

如您所见,无需使用CMAKE_MAKE_PROGRAM,构建默认并行运行,根据可用的 CPU 内核优化作业数量。

Ninja 基于低级 JSON 配置来加快启动阶段。因此它的 JSON 配置不容易手动编写,我总是使用高级工具/IDE 生成它:

由于 C++ 构建通常需要大量内存,因此您的计算机必须提供与 CPU 内核数量一样多的内存。

正如 Ruslan 所指出的,CMake 3.12 (2018) 有一个 new option cmake --build -j <N> 以将构建限制为 <N> 内核(作业),从而限制内存消耗(另请参阅 documentation) .如果您使用较旧的 CMake 版本,您仍然可以使用 cmake --build -- -j <N>-- 选项告诉 CMake 将其余部分直接传递给底层构建器工具,这里是 Ninja。

【讨论】:

  • 关于最后一句话:您可以通过-j N 选项限制使用的核心数量,从而限制使用的内存量。
  • 谢谢 Ruslan ? 在我回答三年后,CMake 终于有了我一直在等待的选项-j N。玩得开心?
  • 在 CMake 3.12 之前,您可以将此选项传递给 Ninja — 可以像在第一个 sn-p 中那样直接运行它,或者在 cmake --build 之后附加 -- -jN-- 的 @ 功能987654345@ 即使在 CMake 2.8.0 中也存在)。
  • 谢谢@Ruslan ?。我知道与make 一起使用的-- 选项。但我从未将它与ninja 一起使用。 ? 也许在 2015 年,ninja 没有选项 -j <N>... 或者我没有正确使用它... ? 我已经更新了答案以适应您的体验。谢谢?
  • 使用新的 cmake -j 选项,如果通过 -j 0 它将自动使用所有核心,例如自动检测最大可用核心并全部使用?
【解决方案3】:

现在使用 cmake 并行构建非常简单。您可以在使用“cmake --build”时添加“-j jobs_number”。例如:

cmake --build . -j 24

更多细节可以在CMAKE手册中找到:https://cmake.org/cmake/help/latest/manual/cmake.1.html#build-tool-mode

--parallel [], -j [] 构建时使用的最大并发进程数。如果省略本机构建 使用工具的默认编号。

CMAKE_BUILD_PARALLEL_LEVEL 环境变量(如果设置)指定 未给出此选项时的默认并行级别。

一些原生构建工具总是并行构建。指某东西的用途 值 1 可用于限制为单个作业。

【讨论】:

  • 当我尝试得到 Unknown argument -j 时。这是在 ubuntu 上,cmake 版本 3.10.2
  • @pellucidcoder 原因可能是你至少需要 CMake 3.12
【解决方案4】:

您不能跨平台执行此操作。 -jN 选项是 make 的一个参数,而不是生成的 Makefile 的一部分。但是,您可以让 CMake 生成一个 Bash 脚本,该脚本使用 -jN 为您的项目运行 make(该脚本会在其中查找您拥有的内核数)。

【讨论】:

  • 对于 Visual Studio:msbuild your_project.sln /maxcpucount:N
  • @JeanDavy:您甚至可以使用 CMake 构建工具通过调用 cmake --build . -- /maxcpucount:8 传递此参数,因为 CMake 会将“空”-- 之后的所有参数传递给构建工具。
  • @RolandSarrazin 是的,我当前的脚本是cmake --build . --target install --config release -- /m,它似乎适用于所有内核。感谢this discussion。我还建议不要指定确切的数字,在这种情况下,MSBuild 会考虑必须在所有可用内核上执行构建,但不能超过存在。
  • 不再正确。从 3.12 开始,CMake 提供相应的标志。看我的回答。
【解决方案5】:

我已经决定为基于Unix Makefiles 的生成器编写parallelmake.sh 脚本。这是在这里完成的:https://github.com/gabyx/ApproxMVBB

以及CMake文件中的相关部分:

https://github.com/gabyx/ApproxMVBB/blob/master/CMakeLists.txt#L89

# Add some multithreaded build support =====================================================================================================
MARK_AS_ADVANCED(MULTITHREADED_BUILD)
SET(MULTITHREADED_BUILD ON CACHE BOOL "Parallel build with as many threads as possible!")
if(MULTITHREADED_BUILD)
    if(${CMAKE_GENERATOR} MATCHES "Unix Makefiles")
            file(COPY ${ApproxMVBB_ROOT_DIR}/cmake/parallelmake.sh DESTINATION ${PROJECT_BINARY_DIR}
                FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
                NO_SOURCE_PERMISSIONS
            )
            SET(CMAKE_MAKE_PROGRAM "${PROJECT_BINARY_DIR}/parallelmake.sh")
            MESSAGE(STATUS "Set make program to ${PROJECT_BINARY_DIR}/parallelmake.sh")
    elseif(MSVC)
      SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" "/MP")
      MESSAGE(STATUS "Added parallel build arguments to CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
    endif()
endif()
# ========================================================================================================================================

【讨论】:

  • 有了CMake 3.12,还是用官方的方式比较好。
【解决方案6】:

如上所述,可以使用 CMake 的--parallel [<jobs>](或-j [<jobs>])选项并行构建解决方案。

但我想指出的是,在 Windows 中是一个命令

cmake.exe --build --parallel <jobs>

使用以下参数启动根 MSBuild 进程:

msbuild.exe /m:<jobs> /p:CL_MPCount=1 <another-useful-arguments>

这意味着将启动多个 MSBuild 进程 -- /maxcpucount:&lt;jobs&gt; aka /m:&lt;jobs&gt;。但是它们中的每一个都最多运行一个编译器进程(有关更多详细信息,请查找this link)。也就是说每个MSBuild最多可以同时编译一个源文件。

要克服这一限制,可以通过以下方式调用 CMake:

cmake.exe --build --parallel <n_msbuild> -- /p:CL_MPcount=<n_cl>

这种方法设置/MP option 从而允许每个MSBuild 实例下有多个编译器进程。


为了记录。要配置从 Visual Studio GUI 运行的构建,需要转到 Settings

  • 选项“项目和解决方案 → 构建和运行 → 并行项目构建的最大数量” 影响 maxcpucount
  • 选项“Projects and Solutions → VC++ Project Settings → Build → Maximum Concurrent C++ Compilations” 表示/MP 的默认边界。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-19
    • 2011-10-06
    • 1970-01-01
    • 2021-07-25
    • 1970-01-01
    • 2021-04-19
    • 1970-01-01
    • 2010-10-07
    相关资源
    最近更新 更多