mpi - 确保混合 MPI/OpenMP 在不同的内核上运行每个 OpenMP 线程

标签 mpi openmp hpc mpich

我正在尝试运行混合 OpenMP/MPI 作业,以便 OpenMP 线程由核心分隔(每个核心只有一个线程)。我已经看到其他使用 numa-ctl 和 bash 脚本来设置环境变量的答案,我不想这样做。

我希望只能通过在命令行上设置 OMP_NUM_THREADS 和或 OMP_PROC_BIND 和 mpiexec 选项来做到这一点。我尝试了以下方法 - 假设我想要 2 个 MPI 进程,每个进程都有 2 个 OpenMP 线程,并且每个线程都在不同的内核上运行,所以我想要总共 4 个内核。

OMP_PROC_BIND=true OMP_PLACES=cores OMP_NUM_THREADS=2 mpiexec -n 2 

这会拆分作业,以便只有两个进程在工作,并且它们都在同一个 CPU 上,因此它们每个只使用大约 25% 的 CPU。如果我尝试:
OMP_PROC_BIND=false OMP_PLACES=cores OMP_NUM_THREADS=2 mpiexec -n 2

然后,我得到了两个独立的 MPI 进程,每个进程都以 100% 或超过 100% 的 CPU 功率运行,根据顶部的说法。这似乎没有显示用于 OpenMP 线程的不同内核。

如何强制系统将单独的线程放在单独的内核上?

仅供引用,lscpu 打印:
-CPU(s):                48
-On-line CPU(s) list:   0-47
-Thread(s) per core:    2
-Core(s) per socket:    12
-Socket(s):             2
-NUMA node(s):          2

最佳答案

实际上,我希望您的第一个示例能够正常工作。设置OMP_PROC_BIND=true这很重要,以便 OpenMP 在固定线程时保持在 MPI 进程的 CPU 绑定(bind)内。

根据批处理系统和 MPI 实现,可能有非常独特的方法来设置这些东西。

此外,超线程,或者通常每个内核的多个硬件线程,在你的 Linux 中都显示为“内核”,可能是问题的一部分,因为当两个进程在一个内核的两个超线程上运行时,你永远不会看到 200%。

这是一个通用的解决方案 ,我在为某些系统上的某些 MPI 和某些 OpenMP 实现计算这些东西时使用。
有来自 Cray 的文档,其中包含 非常帮助快速解决这些问题的程序,它被称为 xthi.c , google the filename或从 here 粘贴(不确定将其粘贴在这里是否合法......)。编译:

mpicc xthi.c -fopenmp -o xthi

现在我们可以看到到底发生了什么,例如在具有超线程和英特尔 MPI(基于 MPICH)的 2x 8 核 Xeon 上,我们得到:
$ OMP_PROC_BIND=true OMP_PLACES=cores OMP_NUM_THREADS=2 mpiexec -n 2 ./xthi

Hello from rank 0, thread 0, on localhost. (core affinity = 0,16)
Hello from rank 0, thread 1, on localhost. (core affinity = 1,17)
Hello from rank 1, thread 0, on localhost. (core affinity = 8,24)
Hello from rank 1, thread 1, on localhost. (core affinity = 9,25)

如您所见,核心意味着一个核心的所有超线程。注意 mpirun默认情况下也将其固定在不同的 socket 上。和 OMP_PLACES=threads每个核心有一个线程:
$ OMP_PROC_BIND=true OMP_PLACES=threads OMP_NUM_THREADS=2 mpiexec -n 2 ./xthi
Hello from rank 0, thread 0, on localhost. (core affinity = 0)
Hello from rank 0, thread 1, on localhost. (core affinity = 1)
Hello from rank 1, thread 0, on localhost. (core affinity = 8)
Hello from rank 1, thread 1, on localhost. (core affinity = 9)

OMP_PROC_BIND=false (你的第二个例子),我得到:
$ OMP_PROC_BIND=false OMP_PLACES=cores OMP_NUM_THREADS=2 mpiexec -n 2 ./xthi
Hello from rank 0, thread 0, on localhost. (core affinity = 0-7,16-23)
Hello from rank 0, thread 1, on localhost. (core affinity = 0-7,16-23)
Hello from rank 1, thread 0, on localhost. (core affinity = 8-15,24-31)
Hello from rank 1, thread 1, on localhost. (core affinity = 8-15,24-31)

在这里,每个 OpenMP 线程都有一个完整的套接字,因此 MPI 等级仍然在不同的资源上运行。但是,一个进程内的 OpenMP 线程可以由操作系统在所有内核上进行疯狂调度。和设置OMP_NUM_THREADS=2一样在我的测试系统上。

同样,这可能取决于特定的 OpenMP 和 MPI 实现和版本,但我认为您会很容易地弄清楚上面的描述发生了什么。

希望有帮助。

关于mpi - 确保混合 MPI/OpenMP 在不同的内核上运行每个 OpenMP 线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47821498/

相关文章:

c - 当数组格式如下时,如何将二维数组传递给 C 中的函数?

c++ - MPI_Bcast : how to ensure that "correct" root is broadcasting 有困难

c++ - 在 MPI_Init() 之前初始化变量,在 MPI_Finanlize() 之后初始化变量

c - 使用 SIMD 和 openMP 加速矩阵乘法

c++ - 从 Fortran 例程调用多线程 (openmp) c++ 例程

openmp - 在 OpenMP 中使用 declare target pragma 的原因

linux - 如何将 qsub 输出流定向到 pwd 而不是 home

eclipse - java.io.FileNotFoundException : null\conf\wrapper. conf(系统找不到指定的路径)

c++ - 如何找到我的线程在哪个 CPU 内核上运行

c - 需要一种快速方法将大量 double 转换为字符串