2

我编写了一个小型测试程序,在其中尝试使用 Windows API 调用 SetThreadAffinityMask 将线程锁定到单个 NUMA 节点。我使用 GetNumaNodeProcessorMask API 调用检索节点的 CPU 位掩码,然后将该位掩码与 GetCurrentThread 返回的线程句柄一起传递给 SetThreadAffinityMask。这是我的代码的一个大大简化的版本:

// Inside a function called from a boost::thread
unsigned long long nodeMask = 0;
GetNumaNodeProcessorMask(1, &nodeMask);
HANDLE thread = GetCurrentThread();
SetThreadAffinityMask(thread, nodeMask);
DoWork(); // make-work function

我当然会检查 API 调用是否在我的代码中返回 0,并且我还打印了 NUMA 节点掩码,这正是我所期望的。我还遵循了其他地方给出的建议,并打印了第二次相同调用 SetThreadAffinityMask 返回的掩码,它与节点掩码匹配。

但是,通过查看 DoWork 函数执行时的资源监视器,工作被分配到所有内核中,而不仅仅是表面上绑定的内核。使用 SetThreadAffinityMask 时我可能错过了哪些错误?我正在运行 Windows 7 Professional 64 位,DoWork 函数包含一个与 OpenMP 并行的循环,该循环对三个非常大的数组的元素执行操作(它们组合起来仍然能够适合节点)。

编辑:为了扩展 David Schwartz 给出的答案,在 Windows 上,任何使用 OpenMP 产生的线程都不会继承产生它们的线程的亲和性。问题在于,而不是 SetThreadAffinityMask。

4

1 回答 1

2

您是否确认其关联掩码的特定线程正在另一个 numa 节点的核心上运行?否则,它会按预期工作。您在一个线程上设置处理器掩码,然后观察一线程的行为。

于 2012-01-24T00:10:00.567 回答