这完全符合我的预期:
#include <cassert>
#include <iostream>
#include <numa.h>
#include <omp.h>
#include <sched.h>
int main() {
assert (numa_available() != -1);
auto nodes = numa_num_configured_nodes();
auto cores = numa_num_configured_cpus();
auto cores_per_node = cores / nodes;
omp_set_nested(1);
#pragma omp parallel num_threads(nodes)
{
auto outer_thread_id = omp_get_thread_num();
numa_run_on_node(outer_thread_id);
#pragma omp parallel num_threads(cores_per_node)
{
auto inner_thread_id = omp_get_thread_num();
#pragma omp critical
std::cout
<< "Thread " << outer_thread_id << ":" << inner_thread_id
<< " core: " << sched_getcpu() << std::endl;
assert(outer_thread_id == numa_node_of_cpu(sched_getcpu()));
}
}
}
程序首先在我的双套接字服务器上创建2个(外部)线程。然后,它将它们绑定到不同的套接字(NUMA节点)。最后,它将每个线程拆分为20个(内部)线程,因为每个CPU有10个物理内核并启用了超线程。
所有内部线程都与其父线程在同一套接字上运行。即外螺纹0的芯线0-9和20-29,以及外螺纹1的芯线10-19和30-39。(
sched_getcpu()
在我的情况下,返回了范围为0-39的虚拟核心数。)
请注意,没有C++11线程,只有纯OpenMP。