我有以下設置,一個混合MPI/OpenMP代碼,其中 運行M個MPI進程,每個進程有N個線程。總共有 可用的MxN線程。將線程綁定到特定的MPI進程
我想這樣做,如果可能的話,就是線程 只分配到一些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 –