MPI topic: Hybrid computing

Experimental html version of Parallel Programming in MPI, OpenMP, and PETSc by Victor Eijkhout. download the textbook at https:/theartofhpc.com/pcse
\[ \newcommand\inv{^{-1}}\newcommand\invt{^{-t}} \newcommand\bbP{\mathbb{P}} \newcommand\bbR{\mathbb{R}} \newcommand\defined{ \mathrel{\lower 5pt \hbox{${\equiv\atop\mathrm{\scriptstyle D}}$}}} \] 13.1 : MPI support for threading
Back to Table of Contents

13 MPI topic: Hybrid computing

While the MPI standard itself makes no mention of threads -- process being the primary unit of computation -- the use of threads is allowed. Below we will discuss what provisions exist for doing so.

Using threads and other shared memory models in combination with MPI leads of course to the question how race condition s are handled. Example of a code with a data race that pertains to MPI:

#pragma omp sections
#pragma omp section
  MPI_Send( x, /* to process 2 */ )
#pragma omp section
  MPI_Recv( x, /* from process 3 */ )
The MPI standard here puts the burden on the user: this code is not legal, and behavior is not defined.

13.1 MPI support for threading

crumb trail: > mpi-hybrid > MPI support for threading

In hybrid execution, the main question is whether all threads are allowed to make MPI calls. To determine this, replace the MPI_Init call by MPI_Init_thread Here the required and provided parameters can take the following (monotonically increasing) values:

After the initialization call, you can query the support level with MPI_Query_thread  .

In case more than one thread performs communication, MPI_Is_thread_main can determine whether a thread is the main thread.

Python note The thread level can be set through the mpi4py.rc object (section  2.2.2  ):

mpi4py.rc.threads # default True
mpi4py.rc.thread_level # default "multiple"
Available levels are multiple  , serialized  , funneled  , single  .

MPL note MPL always calls MPI_Init_thread requesting the highest level MPI_THREAD_MULTIPLE  .

enum mpl::threading_modes {
  mpl::threading_modes::single = MPI_THREAD_SINGLE, 
  mpl::threading_modes::funneled = MPI_THREAD_FUNNELED,
  mpl::threading_modes::serialized = MPI_THREAD_SERIALIZED,
  mpl::threading_modes::multiple = MPI_THREAD_MULTIPLE
};
threading_modes mpl::environment::threading_mode ();
bool mpl::environment::is_thread_main ();
End of MPL note

The mpiexec program usually propagates environment variables  , so the value of OMP_NUM_THREADS when you call mpiexec will be seen by each MPI process.

Exercise Consider the 2D heat equation and explore the mix of MPI/OpenMP parallelism:

Discuss theoretically why the former can give higher performance. Implement both schemes as special cases of the general hybrid case, and run tests to find the optimal mix.
End of exercise

// thread.c
MPI_Init_thread(&argc,&argv,MPI_THREAD_MULTIPLE,&threading);
comm = MPI_COMM_WORLD;
MPI_Comm_rank(comm,&procno);
MPI_Comm_size(comm,&nprocs);

if (procno==0) { switch (threading) { case MPI_THREAD_MULTIPLE : printf("Glorious multithreaded MPI\n"); break; case MPI_THREAD_SERIALIZED : printf("No simultaneous MPI from threads\n"); break; case MPI_THREAD_FUNNELED : printf("MPI from main thread\n"); break; case MPI_THREAD_SINGLE : printf("no threading supported\n"); break; } } MPI_Finalize();

Back to Table of Contents