首页 > 解决方案 > 如何在 Windows 10 上通过 openMP 使用所有 NUMA 节点

问题描述

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

我的代码相对简单,我将 openMP 用于一个看起来像这样的主要可并行循环(k是一个函数参数,缓冲区是一个长度为n的数 GB 数组):

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 实现),但我不知道应该如何手动完成。

任何帮助是极大的赞赏!

标签: cwindowsopenmpaffinitynuma

解决方案


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

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

[编辑] 您也可以手动管理线程。如果你想这样做,我建议深入研究Processtopologyapi.hand processthreadsapi.h,尤其是函数GetActiveProcessorCountand SetThreadGroupAffinity


推荐阅读