2015-11-07 58 views
1

我有以下設置,一個混合MPI/OpenMP代碼,其中 運行M個MPI進程,每個進程有N個線程。總共有 可用的MxN線程。將線程綁定到特定的MPI進程

我想這樣做,如果可能的話,就是線程 只分配到一些MPI進程不是所有的人,我的代碼將 是更有效,因爲一些線程只是在做 重複性的工作。

謝謝。

+1

我不確定我是否理解這個問題。你想保持'M'x'N'線程的全局數量不變,但是有些MPI進程使用多於'N'個線程,而另一些則使用更少的?或者你想實現其他目標嗎? – Gilles

+0

相關? http://stackoverflow.com/questions/11749182/assign-two-mpi-processes-per-core –

回答

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與命令行參數<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變得有點棘手,應該完全關閉。

+0

如果這不是你正在尋找的答案,那我生鏽的水晶球最後一次失敗了...... –

+0

感謝您的解釋。在我的代碼中,我使用「mpirun -n」設置了MPI等級的數量,然後使用「export OMP_NUM_THREADS」設置線程數。然而,這種方法是「不靈活的」,因爲相同數量的線程被分配給每個MPI等級,並且我正在浪費CPU功率,因爲​​許多線程處於空閒或重複任務。這就是爲什麼我想要一些方案爲MPI = 1,2,3分配實例2線程,爲MPI = 4,5,6分配4個線程。在某些時候,我需要設置屏障來同步來自不同MPI的數據。您提到的方法可以解決MPIs問題上的不同線索? – armando

+0

@armando,使用上面概述的方法,您可以爲每個MPI級別設置不同數量的OpenMP線程。如何結合這些線程使用MPI是一個單獨的問題。 MPI在很大程度上並不知道線程的存在,並且所有通信都在進程級別發生,因此每個進程的線程數量不應該存在問題。當然,如果OpenMP線程本身不進行MPI調用。 –