c - 如何在 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 实现),但我不知道应该如何手动完成。
任何帮助是极大的赞赏!
解决方案
我找到了问题的原因。机器上有超过 64 个逻辑核心,因此 Windows 需要两个 CPU 组来处理它们。默认情况下,它将每个 NUMA 节点放在自己的组中。
如果您的物理核心少于 64 个,则修复方法是禁用 HTT,或者在 bios 中禁用 NUMA 分组。在后一种情况下,前 64 个逻辑核心将被分组并在 Windows 中显示为单个 NUMA 节点,其余的放置在第二个节点中。理想的解决方案将取决于您的特定应用程序,无论您是从使用所有内核中受益,还是从超线程中受益。
[编辑] 您也可以手动管理线程。如果你想这样做,我建议深入研究Processtopologyapi.h
and processthreadsapi.h
,尤其是函数GetActiveProcessorCount
and SetThreadGroupAffinity
。
推荐阅读
- rest - 如何使用 REST API 将文件和附件上传到 sobject 记录?
- jovo-framework - Jovo 部署无法找到 ask-clik
- swift - didRegisterForRemoteNotificationsWithDeviceToken 没有被触发 - 推送通知不起作用
- react-native - Expo共享链接不可点击
- java - 从 Java 8 中的对象列表中获取多个属性列表
- javascript - 程序错误时在外部模块中完成写入流
- javascript - 从 node.js 中的 .MHT 文件中提取图像
- javascript - 有没有办法将 React 组件代码显示为
tag?
- hpc - Singularity 容器中的文件所有权和权限
- vue.js - 如何从 vuejs 根路由器中删除#?