将线程绑定到某些MPI进程

时间:2015-11-07 00:14:06

标签: multithreading fortran mpi openmp

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

如果可能,我想做的是分配线程 只有一些MPI进程而不是所有这些进程,我的代码会 因为一些线程正在做,所以效率更高 重复的工作。

感谢。

2 个答案:

答案 0 :(得分:4)

您的问题是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的{​​{1}}个排名,<args1>使用命令行参数n2排名executable_2 , 等等。总共<args2>个流程开始,并且线性分配排名:

n1 + n2 + ... + nk

作为一个更窄的情况,可以指定相同的可执行文件 k 次,以便使用相同的可执行文件获得 k 不同的上下文。 Ranks (from .. to) | Executable ====================|============= 0 .. n1-1 | executable_1 n1 .. n1+n2-1 | executable_2 n1+n2 .. n1+n2+n3-1 | executable_3 ... | ... 可以包括设置特定环境变量的值,例如在你的情况下可能是<local parameters>。指定环境的确切方法因实现而异。使用Open MPI,可以做到:

OMP_NUM_THREADS

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

all_hosts

虽然受到广泛支持,但以前的方法有点不灵活。如果有人愿意怎么办?所有等级除了每第10次按顺序排外?然后命令行变为:

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

更方便的解决方案是提供一个基于进程级别设置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 : \ ... 的包装器。例如,Open MPI的这种包装器看起来像:

OMP_NUM_THREADS

并简单地用作:

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

第三个也是最不灵活的选择是在MPI初始化之后但在任何并行区域之前从程序内调用mpiexec -n M ... mywrapper.sh myprog <args> ,并根据等级设置不同数量的线程:

omp_set_num_threads()

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

答案 1 :(得分:1)

您可以使用绑定核心来完成工作。然后,在执行期间,您可以使用ISO_C_BINDINGS在程序(http://man7.org/linux/man-pages/man2/sched_setaffinity.2.html)中调用sched_setaffinity,因为它是一个C函数。