From d678f839d8db235a7b6bc4e759569cb23a6d068b Mon Sep 17 00:00:00 2001 From: Syine Mineta Date: Tue, 6 Jan 2026 06:10:47 +0900 Subject: [PATCH] Fix remote access bug across NUMA nodes Ensure that thread-local data is created within the correct NUMA context, so that thread stacks or thread-local storage are allocated to proper NUMA nodes. refs https://github.com/official-stockfish/Stockfish/issues/6516 closes https://github.com/official-stockfish/Stockfish/pull/6518 No functional change --- src/thread.cpp | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/thread.cpp b/src/thread.cpp index c485697da..441af563d 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -213,22 +213,31 @@ void ThreadPool::set(const NumaConfig& numaConfig, while (threads.size() < requested) { - const size_t threadId = threads.size(); - const NumaIndex numaId = doBindThreads ? boundThreadToNumaNode[threadId] : 0; - auto manager = threadId == 0 ? std::unique_ptr( - std::make_unique(updateContext)) - : std::make_unique(); + const size_t threadId = threads.size(); + const NumaIndex numaId = doBindThreads ? boundThreadToNumaNode[threadId] : 0; + auto create_thread = [&]() { + auto manager = threadId == 0 + ? std::unique_ptr( + std::make_unique(updateContext)) + : std::make_unique(); - // When not binding threads we want to force all access to happen - // from the same NUMA node, because in case of NUMA replicated memory - // accesses we don't want to trash cache in case the threads get scheduled - // on the same NUMA node. - auto binder = doBindThreads ? OptionalThreadToNumaNodeBinder(numaConfig, numaId) - : OptionalThreadToNumaNodeBinder(numaId); + // When not binding threads we want to force all access to happen + // from the same NUMA node, because in case of NUMA replicated memory + // accesses we don't want to trash cache in case the threads get scheduled + // on the same NUMA node. + auto binder = doBindThreads ? OptionalThreadToNumaNodeBinder(numaConfig, numaId) + : OptionalThreadToNumaNodeBinder(numaId); - threads.emplace_back(std::make_unique(sharedState, std::move(manager), threadId, - counts[numaId]++, threadsPerNode[numaId], - binder)); + threads.emplace_back(std::make_unique(sharedState, std::move(manager), + threadId, counts[numaId]++, + threadsPerNode[numaId], binder)); + }; + + // Ensure the worker thread inherits the intended NUMA affinity at creation. + if (doBindThreads) + numaConfig.execute_on_numa_node(numaId, create_thread); + else + create_thread(); } clear();