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

时间:2018-09-27 20:45:27

标签: c windows openmp affinity numa

我可以访问由两个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实现),但我不知道我应该如何手动进行。

非常感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

我找到了问题的原因。计算机上有超过64个逻辑核心,因此Windows需要两个CPU组来对其进行寻址。默认情况下,它将每个NUMA节点放在自己的组中。

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

[编辑] 您也可以手动管理线程。如果您想这样做,建议您深入研究Processtopologyapi.hprocessthreadsapi.h,尤其是功能GetActiveProcessorCountSetThreadGroupAffinity