multithreading - 将线程绑定(bind)到某些 MPI 进程

标签 multithreading fortran mpi openmp

我有以下设置,混合 MPI/OpenMP 代码
运行 M 个 MPI 进程,每个进程有 N 个线程。总共有
MxN 线程可用。

如果可能的话,我想做的是分配线程
仅适用于某些 MPI 进程,而不适用于所有进程,我的代码将
更有效率,因为一些线程只是在做
重复的工作。

谢谢。

最佳答案

您的问题是 this one 的通用版本.至少有三种可能的解决方案。

对于大多数 MPI 实现,可以使用它们自己的环境(上下文)启动多个可执行文件,作为同一个 MPI 作业的一部分。它被称为 MPMD(多程序多数据)或 MIMD(多指令多数据)模型。语法通常涉及 : (冒号)作为分隔符:

$ mpiexec <global parameters>
          -n n1 <local parameters> executable_1 <args1> :
          -n n2 <local parameters> executable_2 <args2> :
          ...
          -n nk <local parameters> executable_k <argsk>

它启动 n1排名运行executable_1带有命令行参数 <args1> , n2排名运行executable_2带有命令行参数 <args2> , 等等。总计 n1 + n2 + ... + nk进程启动并线性分配等级:

 Ranks (from .. to) |  Executable
====================|=============
0     .. n1-1       | executable_1
n1    .. n1+n2-1    | executable_2
n1+n2 .. n1+n2+n3-1 | executable_3
...                 | ...

作为更狭义的情况,可以指定相同的可执行文件 k 次,以获得具有相同可执行文件的 k 个不同上下文。 <local parameters>可能包括设置特定环境变量的值,例如在您的情况下,可能是 OMP_NUM_THREADS .指定环境的确切方法因一种实现而异。使用 Open MPI,可以:

mpiexec --hostfile all_hosts \
        -n 5 -x OMP_NUM_THREADS=2 myprog : \
        -n 4 -x OMP_NUM_THREADS=4 myprog : \
        -n 6 -x OMP_NUM_THREADS=1 myprog

这将在 all_hosts 中指定的主机上启动 15 个 MPI 等级。 (全局参数)前五个使用两个 OpenMP 线程,接下来的四个 - 四个 OpenMP 线程,最后六个按顺序运行。对于基于 MPICH 的实现,命令会略有不同:

mpiexec --hostfile all_hosts \
        -n 5 -env OMP_NUM_THREADS 2 myprog : \
        -n 4 -env OMP_NUM_THREADS 4 myprog : \
        -n 6 -env OMP_NUM_THREADS 1 myprog

虽然得到了广泛的支持,但以前的方法有点不灵活。如果一个人想要例如怎么办?除了每 10 次按顺序运行之外的所有等级?那么命令行就变成了:

mpiexec ...
        -n 9 -x OMP_NUM_THREADS=1 myprog : \
        -n 1 -x OMP_NUM_THREADS=N myprog : \
        -n 9 -x OMP_NUM_THREADS=1 myprog : \
        -n 1 -x OMP_NUM_THREADS=N myprog : \
        ...

一个更方便的解决方案是提供一个设置 OMP_NUM_THREADS 的包装器。基于进程等级。例如,这样的 Open MPI 包装器如下所示:

#!/bin/bash
if [ $((($OMPI_COMM_WORLD_RANK + 1) % 10)) == 0 ]; then
  export OMP_NUM_THREADS=N
else
  export OMP_NUM_THREADS=1
fi
exec "$*"

并简单地用作:

mpiexec -n M ... mywrapper.sh myprog <args>

第三个也是最不灵活的选择是简单地调用omp_set_num_threads()。在 MPI 初始化之后但在任何并行区域之前从程序内部,并根据等级设置不同的线程数:

integer :: provided, rank, ierr

call MPI_INIT_THREAD(MPI_THREAD_FUNNELED, provided, ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)

if (mod(rank, 10) == 0) then
   call omp_set_num_threads(N)
else
   call omp_set_num_threads(1)
end if

无论选择哪种解决方案,进程和线程绑定(bind)都会变得有点棘手,可能应该完全关闭。

关于multithreading - 将线程绑定(bind)到某些 MPI 进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33577584/

相关文章:

fortran - Fortran 中的指针数组

loops - Fortran 2018+ 中过时的 DO 循环

floating-point - Fortran 中具有 NaN 值的参数(常量)变量

Android:使用 "progress"GUI 在后台线程中从 Web 加载数据?

c 编程实现不同应用程序的互斥

使用 mpicc 编译非 mpi 库

c++ - MPI_Recv - 如何确定计数?

c - MPI_发送(99)。 : Invalid tag, 值为-1

java - java中的线程和同步

c# - 为一个结果等待多个线程