PAYATHON 2026

如何在 CMake 中按 CPU 核心数设置并行构建任务?

数据小许

结论

ProcessorCount 和 cmake_host_system_information() 可以在 CMake 配置阶段查询核心数,但 CMakePresets.json 的 jobs 属性不能动态计算。CMAKE_BUILD_PARALLEL_LEVEL 则是在运行 cmake --build 时读取的环境变量。在 CMakeLists.txt 中设置普通变量,不会影响之后单独启动的构建命令。

如果要根据核心数选择任务数,可以用 CMake 脚本计算,再依次运行配置和构建。这样只需执行一个入口命令。下面的示例将任务数设为逻辑核心数减 1,并确保结果至少为 1。

使用 CMake 脚本串联配置和构建

将下面的内容保存为项目根目录下的 build.cmake。把示例中的 dev 改成项目实际使用的 configure preset 和 build preset 名称,然后在包含 CMakePresets.json 的项目根目录运行脚本。

cmake_minimum_required(VERSION 3.22)

cmake_host_system_information(
  RESULT logical_cores
  QUERY NUMBER_OF_LOGICAL_CORES
)

if(NOT logical_cores OR logical_cores LESS 1)
  set(jobs 1)
else()
  math(EXPR jobs "${logical_cores} - 1")
  if(jobs LESS 1)
    set(jobs 1)
  endif()
endif()

execute_process(
  COMMAND "${CMAKE_COMMAND}" --preset dev
  RESULT_VARIABLE configure_result
)
if(NOT configure_result EQUAL 0)
  message(FATAL_ERROR "CMake 配置失败,退出码:${configure_result}")
endif()

execute_process(
  COMMAND "${CMAKE_COMMAND}" --build --preset dev --parallel "${jobs}"
  RESULT_VARIABLE build_result
)
if(NOT build_result EQUAL 0)
  message(FATAL_ERROR "构建失败,退出码:${build_result}")
endif()

运行:

cmake -P build.cmake

--parallel <jobs> 会将算出的任务数传给构建步骤。要按物理核心数计算,可以将查询改为 NUMBER_OF_PHYSICAL_CORES,并根据需要为查询结果为空或小于 1 的情况设置兜底值。

为什么预设和 CMakeLists.txt 不能直接完成动态计算

构建预设中的 jobs 是一个固定值。预设 JSON 不会执行 CMake 命令或计算表达式,因此不能在 CMakePresets.json 中调用 ProcessorCount(),再将结果减 1。

在 CMakeLists.txt 中设置 CMAKE_BUILD_PARALLEL_LEVEL,也不会改变用户之后运行构建命令时的进程环境。这个变量需要由外部脚本、终端或 CI 环境提供。例如,在 shell 中可以这样设置:

CMAKE_BUILD_PARALLEL_LEVEL=8 cmake --build --preset dev

这里的 8 只是固定示例值。若要根据核心数动态选择任务数,仍需由外部脚本计算,也可以像前面的示例那样,直接向 cmake --build 传入 --parallel 参数。

关于两种核心数策略

逻辑核心数减 1 和物理核心数是两种不同的启发式策略,无法保证在所有机器上效果相同。前一种策略会空出一个逻辑处理器;后一种则按物理核心数限制并行任务。选哪种取决于你希望为交互任务留出多少资源。核心数查询只能提供参考,无法准确反映用户当前的负载。

备注:内容仅供参考。