Skip to content

Commit d678f83

Browse files
MinetaSvondele
authored andcommitted
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 official-stockfish#6516 closes official-stockfish#6518 No functional change
1 parent 28844fc commit d678f83

File tree

1 file changed

+25
-16
lines changed

1 file changed

+25
-16
lines changed

src/thread.cpp

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -213,22 +213,31 @@ void ThreadPool::set(const NumaConfig& numaConfig,
213213

214214
while (threads.size() < requested)
215215
{
216-
const size_t threadId = threads.size();
217-
const NumaIndex numaId = doBindThreads ? boundThreadToNumaNode[threadId] : 0;
218-
auto manager = threadId == 0 ? std::unique_ptr<Search::ISearchManager>(
219-
std::make_unique<Search::SearchManager>(updateContext))
220-
: std::make_unique<Search::NullSearchManager>();
221-
222-
// When not binding threads we want to force all access to happen
223-
// from the same NUMA node, because in case of NUMA replicated memory
224-
// accesses we don't want to trash cache in case the threads get scheduled
225-
// on the same NUMA node.
226-
auto binder = doBindThreads ? OptionalThreadToNumaNodeBinder(numaConfig, numaId)
227-
: OptionalThreadToNumaNodeBinder(numaId);
228-
229-
threads.emplace_back(std::make_unique<Thread>(sharedState, std::move(manager), threadId,
230-
counts[numaId]++, threadsPerNode[numaId],
231-
binder));
216+
const size_t threadId = threads.size();
217+
const NumaIndex numaId = doBindThreads ? boundThreadToNumaNode[threadId] : 0;
218+
auto create_thread = [&]() {
219+
auto manager = threadId == 0
220+
? std::unique_ptr<Search::ISearchManager>(
221+
std::make_unique<Search::SearchManager>(updateContext))
222+
: std::make_unique<Search::NullSearchManager>();
223+
224+
// When not binding threads we want to force all access to happen
225+
// from the same NUMA node, because in case of NUMA replicated memory
226+
// accesses we don't want to trash cache in case the threads get scheduled
227+
// on the same NUMA node.
228+
auto binder = doBindThreads ? OptionalThreadToNumaNodeBinder(numaConfig, numaId)
229+
: OptionalThreadToNumaNodeBinder(numaId);
230+
231+
threads.emplace_back(std::make_unique<Thread>(sharedState, std::move(manager),
232+
threadId, counts[numaId]++,
233+
threadsPerNode[numaId], binder));
234+
};
235+
236+
// Ensure the worker thread inherits the intended NUMA affinity at creation.
237+
if (doBindThreads)
238+
numaConfig.execute_on_numa_node(numaId, create_thread);
239+
else
240+
create_thread();
232241
}
233242

234243
clear();

0 commit comments

Comments
 (0)