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();