我写了一个小的testing程序,我尝试使用Windows API调用SetThreadAffinityMask将线程locking到单个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节点掩码,这正是我所期望的。 我也遵循其他地方给出的build议,并打印出由第二个相同的调用SetThreadAffinityMask返回的掩码,它与节点掩码相匹配。
但是,从DoWork函数执行时看资源监视器,工作被拆分到所有内核中,而不是仅仅被看作是绑定的那些内核。 使用SetThreadAffinityMask时,有没有可能错过的旅程? 我正在运行Windows 7 Professional 64位,DoWork函数包含一个与OpenMP并行的循环,它对三个非常大的数组(这些数组合仍然能够适应节点)的元素执行操作。
编辑:为了扩展David Schwartz给出的答案,在Windows上,OpenMP生成的任何线程都不会inheritance产生它们的线程的亲和性。 问题在于,不是SetThreadAffinityMask。
您是否确认亲和性掩码在另一个numa节点的核心上运行的特定线程? 否则,它按预期工作。 您在一个线程上设置处理器掩码,然后观察一组线程的行为。