Skip to content

Set process affinity upon match start.#924

Merged
Disservin merged 3 commits intoDisservin:masterfrom
JoostHouben:windows-affinity
Sep 28, 2025
Merged

Set process affinity upon match start.#924
Disservin merged 3 commits intoDisservin:masterfrom
JoostHouben:windows-affinity

Conversation

@JoostHouben
Copy link
Copy Markdown
Contributor

@JoostHouben JoostHouben commented Sep 28, 2025

Fixes #922.

The previous approach has a couple of issues:

  1. The setAffinity function (as written) on Windows only works for setting process affinity, not for setting thread affinity. For thread affinity, a different set of Windows APIs needs to be used. However, the function is used for setting thread affinity (in BaseTournament::playGame).
  2. In BaseTournament::playGame, the return code of setAffinity was not checked, so even though this call always fails on Windows, the failure was ignored.
  3. On Windows, child processes inherit their parent process's affinity, not the affinity of the thread from which they were created. So even if the tournament thread's affinity is set correctly, it won't propagate to the engine processes.

In other words: the logic from #867 simply doesn't apply to Windows. The logic there assumes the Linux model of affinities, where (IIUC) affinity is a thread-level property, processes only have an affinity insofar as their main thread does, and threads inherit their affinity from parent threads, even across process boundaries.

In this PR I fix this by:

  • Splitting setAffinity into setThreadAffinity and setProcessAffinity so that semantics on different platforms can be correctly represented. On Linux, setProcessAffinity can simply call setThreadAffinity, which will set the affinity of the process's main thread (the existing behavior).
  • Explicitly setting process affinity as part of starting the engine processes in UciEngine::start. On Linux this shouldn't have any effect if the tournament's thread affinity is already set.
  • Adding error logging to BaseTournament::playGame so that failure to set thread affinity isn't silently ignored
  • Making all affinity:: functions [[nodiscard]]

Additionally, the Makefile is modified to use static linking on Windows for debug builds. It might just be how my environment is set up, but when building in debug mode (with msys2 and ucrt64), I wasn't able to run the resulting binary because it couldn't find the required DLLs. Making the build static fixes this problem, making debugging easier. Note that under release we always produce a statically linked binary regardless.

Testing done:

  • Verified that CPU affinity is respected for a test tournament with my engine Euwe (using concurrency of 64 on Windows 11 with a 64 core / 128 thread processor):
    image
  • Verified the same is true for a tournament between instances of Stockfish 17.
  • Ran unit tests on WSL (still can't figure out how to make those run on Windows).

@JoostHouben JoostHouben marked this pull request as ready for review September 28, 2025 05:32
@Disservin Disservin merged commit bb48353 into Disservin:master Sep 28, 2025
18 checks passed
@Disservin
Copy link
Copy Markdown
Owner

thanks!

@JoostHouben JoostHouben deleted the windows-affinity branch September 28, 2025 22:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows Affinity Not Respected

2 participants