在 MPICH 中执行混合 OpenMP/MPI 作业

Posted

技术标签:

【中文标题】在 MPICH 中执行混合 OpenMP/MPI 作业【英文标题】:Executing hybrid OpenMP/MPI jobs in MPICH 【发布时间】:2016-02-15 06:24:00 【问题描述】:

我正在努力寻找使用 MPICH (hydra) 执行混合 OpenMP/MPI 作业的正确方法。

我可以轻松启动这些进程,并且它们确实会创建线程,但无论我尝试过哪种类型的 -bind-to,它们都被绑定到与其主线程相同的核心。

如果我将GOMP_CPU_AFFINITY 明确设置为0-15,我会分散所有线程,但仅在每个节点有1 个进程时才提供。我不希望这样,我希望每个套接字一个进程。

设置OMP_PROC_BIND=false 没有明显效果。

我尝试过的许多不同组合的示例

export OMP_NUM_THREADS=8
export OMP_PROC_BIND="false"
mpiexec.hydra -n 2 -ppn 2 -envall -bind-to numa  ./a.out

我得到的是所有进程都坐在一个核心 0-7 上,100% 和几个线程在核心 8-15 但只有一个接近 100%(他们正在等待第一个进程)。

【问题讨论】:

【参考方案1】:

当 MPI 库和 OpenMP 运行时在默认情况下不能很好地协作时,当运行混合的 MPI/OpenMP 代码时,我确实有一个稍微不同的解决方案来将 OpenMP 线程绑定到套接字/NUMA 节点。这个想法是使用numactl 及其绑定属性。这甚至具有额外的优势,不仅将线程绑定到套接字,还绑定内存,从而强制实现良好的内存局部性并最大化带宽。

为此,我首先禁用任何 MPI 和/或 OpenMP 绑定(前者使用相应的 mpiexec 选项,后者将 OMP_PROC_BIND 设置为 false)。然后我使用下面的omp_bind.sh shell 脚本:

#!/bin/bash

numactl --cpunodebind=$(( $PMI_ID % 2 )) --membind=$(( $PMI_ID % 2 )) "$@"

我以这种方式运行我的代码:

OMP_PROC_BIND="false" OMP_NUM_THREADS=8 mpiexec -ppn 2 -bind-to-none omp_bind.sh a.out args

根据机器上的套接字数量,2 需要在 shell 上进行调整。同样,PMI_ID 取决于使用的mpiexec 的版本。我有时看到MPI_RANKPMI_RANK等。

但无论如何,我总能找到一种让它工作的方法,而且内存绑定有时非常方便,尤其是为了避免 IO 缓冲区耗尽第一个 NUMA 节点上的所有内存的潜在陷阱,从而导致代码的内存对于在第一个套接字上运行的进程,在第二个 NUMA 节点上分配内存。

【讨论】:

有趣。您是否正在使用numactl --membind,因为 MPICH 和兄弟姐妹无法自行进行内存绑定? Open MPI 进行内存绑定,甚至在共享内存传输中实现一些 NUMA 优化。只是出于好奇而询问 - 我是 Open MPI(在很小程度上是英特尔 MPI)用户,而 MPICH 和 co 对我来说非常陌生。 @HristoIliev TBH,我很久以前就计划这样做,因为有时我必须在未正确配置 MPI 的机器上运行性能测试。以这种方式使用numactl 比尝试修复 MPI 配置要简单得多。而此时 OpenMP 还没有任何原生绑定。如今,我主要是英特尔 MPI 用户,但我不太确定那里是如何管理内存绑定的。可以肯定的是,这个旧的 numactl 技巧在需要时仍然有效,此外,通过自愿设置错误,它允许评估代码对代码的潜在 NUMA 影响 感谢您的其他选择。我会调查这两个。我有一些性能问题,看看效果会很有趣。【参考方案2】:

由于libgomp 缺少英特尔KMP_AFFINITYrespect 子句的等效项,您可以通过提供一个从/proc/PID/status(Linux 特定)读取允许的CPU 列表的包装脚本来破解它:

#!/bin/sh

GOMP_CPU_AFFINITY=$(grep ^Cpus_allowed_list /proc/self/status | grep -Eo '[0-9,-]+')
export GOMP_CPU_AFFINITY
exec $*

这应该适用于-bind-to numa

【讨论】:

我想你想要grep ^Cpus_allowed_list /proc/self/status | grep -Eo '[0-9,-]+',这行得通! 实际上我错过了cat,但你的更好。

以上是关于在 MPICH 中执行混合 OpenMP/MPI 作业的主要内容,如果未能解决你的问题,请参考以下文章

OpenMP、MPI、POSIX 线程、std::thread、boost::thread 如何关联?

如何查看 MPICH 的版本?

我是用 OpenMPI 还是 MPICH 编译的?

MPICH/OpenMPI 中的容错

MPICH配置安装与入门

MPICH2 gethostbyname 失败