将线程绑定到特定的MPI进程
我有以下设置,一个混合MPI/OpenMP代码,其中 运行M个MPI进程,每个进程有N个线程。总共有 可用的MxN线程。将线程绑定到特定的MPI进程
我想这样做,如果可能的话,就是线程 只分配到一些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
行列命令行参数<args2>
,等等运行executable_2
。在总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
... | ...
由于更窄的情况下,相同的可执行可以按顺序指定ķ次获得ķ不同的上下文中使用相同的可执行文件。 <local parameters>
可以包括设置特定环境变量的值,例如,在你的情况下,可能是OMP_NUM_THREADS
。指定环境的确切方法因实现而异。随着开放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
,将启动15 MPI使用两个OpenMP的线程all_hosts
(全局参数)指定的主机与前五行列,未来四 - 四个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
。例如,对于开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>
第三和至少灵活的选择是MPI初始化后简单地调用omp_set_num_threads()
从程序中但在此之前根据排名线程的任何并行区域,并设置不同的数字:
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
无论选择何种解决方案,进程和线程绑定ing变得有点棘手,应该完全关闭。
如果这不是你正在寻找的答案,那我生锈的水晶球最后一次失败了...... –
感谢您的解释。在我的代码中,我使用“mpirun -n”设置了MPI等级的数量,然后使用“export OMP_NUM_THREADS”设置线程数。然而,这种方法是“不灵活的”,因为相同数量的线程被分配给每个MPI等级,并且我正在浪费CPU功率,因为许多线程处于空闲或重复任务。这就是为什么我想要一些方案为MPI = 1,2,3分配实例2线程,为MPI = 4,5,6分配4个线程。在某些时候,我需要设置屏障来同步来自不同MPI的数据。您提到的方法可以解决MPIs问题上的不同线索? – armando
@armando,使用上面概述的方法,您可以为每个MPI级别设置不同数量的OpenMP线程。如何结合这些线程使用MPI是一个单独的问题。 MPI在很大程度上并不知道线程的存在,并且所有通信都在进程级别发生,因此每个进程的线程数量不应该存在问题。当然,如果OpenMP线程本身不进行MPI调用。 –
您可以使用绑定到内核来执行您的工作。然后,在执行过程中,您可以使用ISO_C_BINDINGS在程序中调用sched_setaffinity(http://man7.org/linux/man-pages/man2/sched_setaffinity.2.html),因为它是C函数。
我不确定我是否理解这个问题。你想保持'M'x'N'线程的全局数量不变,但是有些MPI进程使用多于'N'个线程,而另一些则使用更少的?或者你想实现其他目标吗? – Gilles
相关? http://stackoverflow.com/questions/11749182/assign-two-mpi-processes-per-core –