Skip to content

Commit

Permalink
Tweak Windows build parallelization settings (#19664)
Browse files Browse the repository at this point in the history
### Description
<!-- Describe your changes. -->
Use UseMultiToolTask and limit the number of cl.exe instances running. 

MultiToolTask info:
https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/

Info on why limiting CL_MPCount can help:
https://github.com/Microsoft/checkedc-clang/wiki/Parallel-builds-of-clang-on-Windows

The current CIs have 4 cores (both physical and logical). Hardcoded the
GPU build in win-ci.yml to use CL_MPCount of 2 as that seems to work
fine. Can adjust if needed to base it on the actual number of cores or
to use build.py to build.

Caveat: I've run about 16 builds and haven't seen a slow build yet, but
as the root cause of the slow builds isn't really known this isn't
guaranteed to be a fix.

### Motivation and Context
<!-- - Why is this change required? What problem does it solve?
- If it fixes an open issue, please link to the issue here. -->
Try and prevent super slow GPU builds by reducing number of tasks
potentially running in parallel.
  • Loading branch information
skottmckay authored Feb 27, 2024
1 parent 3b46ab6 commit 580ee20
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 2 deletions.
15 changes: 14 additions & 1 deletion tools/ci_build/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -1451,6 +1451,13 @@ def generate_build_tree(
# tools need to use the symbols.
add_default_definition(cmake_extra_defines, "CMAKE_MSVC_DEBUG_INFORMATION_FORMAT", "ProgramDatabase")

if number_of_parallel_jobs(args) > 0:
# https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/
# NOTE: this disables /MP if set (according to comments on blog post).
# By default, MultiProcMaxCount and CL_MPCount value are equal to the number of CPU logical processors.
# See logic around setting CL_MPCount below
cmake_args += ["-DCMAKE_VS_GLOBALS=UseMultiToolTask=true;EnforceProcessCountAcrossBuilds=true"]

cmake_args += [f"-D{define}" for define in cmake_extra_defines]

cmake_args += cmake_extra_args
Expand Down Expand Up @@ -1662,11 +1669,17 @@ def build_targets(args, cmake_path, build_dir, configs, num_parallel_jobs, targe
build_tool_args = []
if num_parallel_jobs != 1:
if is_windows() and args.cmake_generator != "Ninja" and not args.build_wasm:
# https://github.com/Microsoft/checkedc-clang/wiki/Parallel-builds-of-clang-on-Windows suggests
# not maxing out CL_MPCount
# Start by having one less than num_parallel_jobs (default is num logical cores),
# limited to a range of 1..3
# that gives maxcpucount projects building using up to 3 cl.exe instances each
build_tool_args += [
f"/maxcpucount:{num_parallel_jobs}",
# one less than num_parallel_jobs, at least 1, up to 3
f"/p:CL_MPCount={min(max(num_parallel_jobs - 1, 1), 3)}",
# if nodeReuse is true, msbuild processes will stay around for a bit after the build completes
"/nodeReuse:False",
f"/p:CL_MPCount={num_parallel_jobs}",
]
elif args.cmake_generator == "Xcode":
build_tool_args += [
Expand Down
3 changes: 2 additions & 1 deletion tools/ci_build/github/azure-pipelines/templates/win-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,11 @@ stages:
platform: ${{ parameters.msbuildPlatform }}
configuration: RelWithDebInfo
msbuildArchitecture: ${{ parameters.buildArch }}
maximumCpuCount: true
maximumCpuCount: true # default is num logical cores worth of projects building concurrently
logProjectEvents: true
workingFolder: '$(Build.BinariesDirectory)\RelWithDebInfo'
createLogFile: true
msbuildArgs: "/p:CL_MPCount=2" # 2x cl.exe per project building.

- task: PythonScript@0
displayName: 'test'
Expand Down

0 comments on commit 580ee20

Please sign in to comment.