如何在 Windows 10 上使用带有 openMP 的所有 NUMA 节点

How to use all NUMA nodes with openMP on Windows 10

我可以访问由两个 NUMA 节点组成的双路系统来进行一些数据处理。

我的代码相对简单,我将 openMP 用于主并行循环,如下所示(k 是一个函数参数,buffer 是长度为 n):

的多千兆字节数组
uint64_t m=0;
uint64_t *rk = (uint64_t *) calloc(k, sizeof(uint64_t));
#pragma omp parallel
{
    #pragma omp for reduction(+:m), reduction(+:rk[:k])
    for (uint64_t i=0; i<n-k; i++)
    {
        m += (uint64_t)buffer[i];
        for (uint64_t j=0; j<k; j++)
        {
            rk[j] += (uint64_t)buffer[i]*(uint64_t)buffer[i+j];
        }
    }
    /* Other stuff, serial and parallel */
}

在 Linux Mint 下,我可以毫无问题地使用 gcc 进行编译,并且两个插槽上的所有内核都得到了很好的利用。但是,在 Windows(cygwin 上的 mingw-gcc)上,只使用了一个 NUMA 节点。因为我的代码对内存延迟并不敏感,所以我在 Windows 上减速了 2 倍。

我不知道如何强制 Windows 在两个节点上分布线程。据我所知,openMP 不支持 Windows 上的亲和力(无论如何都是 cygwin mingw-gcc 实现),但我不知道应该如何手动完成。

非常感谢任何帮助!

我找到了问题的原因。机器上有超过 64 个逻辑核心,因此 Windows 需要两个 CPU 组来解决它们。默认情况下,它将每个 NUMA 节点放在自己的组中。

如果您的物理内核少于 64 个,修复方法是禁用 HTT,或者禁用 bios 中的 NUMA 分组。在后一种情况下,前 64 个逻辑内核将被分组并在 Windows 中显示为单个 NUMA 节点,其余的则放置在第二个节点中。理想的解决方案将取决于您的特定应用程序,无论您是受益于使用所有内核还是受益于超线程..

[编辑] 您也可以手动管理线程。如果你想这样做,我建议深入研究 Processtopologyapi.hprocessthreadsapi.h,特别是研究函数 GetActiveProcessorCountSetThreadGroupAffinity.