在大規模節點間的並行時,由於節點間通訊的量是成平方項增長的,所以帶寬很快就會顯得不夠。所以一種思路增加程序效率線性的方法是用MPI/OPENMP混合編寫並行部分。這一部分其實在了解了MPI和OPENMP以后相對容易解決點。大致思路是每個節點分配1-2個MPI進程后,每個MPI進程執行多個OPENMP線程。OPENMP部分由於不需要進程間通信,直接通過內存共享方式交換信息,不走網絡帶寬,所以可以顯著減少程序所需通訊的信息。
Fortran:
Program hello
use mpi
use omp_lib
Implicit None
Integer :: myid,numprocs,rc,ierr
Integer :: i,j,k,tid
Call MPI_INIT(ierr)
Call MPI_COMM_RANK(MPI_COMM_WORLD,myid,ierr)
Call MPI_COMM_SIZE(MPI_COMM_WORLD,numprocs,ierr)
!$OMP Parallel private(tid)
tid=OMP_GET_THREAD_NUM()
write(*,*) 'hello from',tid,'of process',myid
!$OMP END PARALLEL
Call MPI_FINALIZE(rc)
Stop
End Program hello
C++:
# include <cstdlib>
# include <iostream>
# include <ctime>
# include "mpi.h"
# include "omp.h"
using namespace std;
int main ( int argc, char *argv[] );
//****************************************************************************80
int main ( int argc, char *argv[] )
{
int myid;
int nprocs;
int this_thread;
MPI::Init();
myid=MPI::COMM_WORLD.Get_rank();
nprocs=MPI::COMM_WORLD.Get_size();
#pragma omp parallel private(this_thread)
{
this_thread=omp_get_thread_num();
cout <<this_thread<<" thread from "<<myid<<" is ok\n";
}
MPI::Finalize();
return 0;
}
這里值得要注意的是,似乎直接用mpif90/mpicxx編譯的庫會報錯,所以需要用
icc -openmp hello.cpp -o hello -DMPICH_IGNORE_CXX_SEEK -L/Path/to/mpi/lib/ -lmpi_mt -lmpiic -I/path/to/mpi/include
其中-DMPICH_IGNORE_CXX_SEEK為防止MPI2協議中一個重復定義問題所使用的選項,為了保證線程安全,必須使用mpi_mt庫
對於intel的mpirun,必須在mpirun后加上-env I_MPI_PIN_DOMAIN omp使得每個mpi進程會啟動openmp線程。
通過export OMP_NUM_THREADS來控制每個MPI產生多少線程。