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

Executing hybrid OpenMP/MPI jobs in MPICH

我正在努力寻找使用 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%(它们正在等待第一个过程)。

由于 libgomp 缺少相当于英特尔 KMP_AFFINITYrespect 子句的等价物,您可以通过提供一个包装脚本来破解它,该脚本从 /proc/PID/status(Linux-具体):

#!/bin/sh

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

这应该与 -bind-to numa 一起使用。

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

为此,我首先禁用任何 MPI and/or 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 节点上的所有内存的潜在陷阱,从而导致第一个套接字上 运行ning 进程的代码内存,在第二个 NUMA 节点上分配内存。