MPI¶
Usage
use MPI;
or
import MPI;
Submodules
MPI Bindings for Chapel.
Note
This is a prototype of the MPI interface for Chapel. The feature set, configuration support, and documentation are expected to improve over time.
MPI Version¶
This module implements the C-API for the MPI 1.1 standard. It currently does not support the following routines
MPI_Op_create
MPI_Op_free
MPI_Errhandler_create
MPI_Errhandler_free
MPI_Keyval_create
MPI_Keyval_free
since all of these are built around user-defined handlers, that is not supported.
This module also includes a few functions that are in later MPI standards. These are
MPI_Init_thread (and related constants)
MPI_Ibarrier
Compiler wrappers¶
Using MPI requires pointing the compiler to the location of the
MPI headers, and including the appropriate MPI libraries. This is
often done by using compiler wrappers like “mpicc”. Setting
CHPL_TARGET_COMPILER=mpi-gnu
and CHPL_TARGET_CPU=none
will
get Chapel to use mpicc and assume that it works like gcc does.
Note that on Cray systems, this is not necessary, since the default compilers include the necessary MPI information.
Note
Currently, only the gnu compilers wrapped by MPI are supported. This class is expected to broaden in the future.
Interoperability Modes¶
There are two modes in which Chapel and MPI can interoperate with one another:
SPMD Mode¶
SPMD mode (MPI + single locale Chapel) has no constraints on the setup of Chapel and MPI, and is conceptually the same as OpenMP+MPI programming. All communication here is handled by MPI; Chapel is just used to provide local parallelism. Furthermore, in this mode, Chapel locales do not map to MPI ranks at all; the program just sees a single locale. Note that the same caveats that apply to OpenMP+MPI programming apply here. For instance, MPI must be initialized with the appropriate thread support (see below).
Setting up SPMD mode on a Cray:
The recommended configuration for running multilocale MPI jobs on a Cray is as follows:
CHPL_TARGET_COMPILER=cray-prgenv-gnu
CHPL_TASKS=fifo
CHPL_COMM=none
MPICH_MAX_THREAD_SAFETY=multiple
These are the configurations in which this module is currently tested.
Note
Currently, running SPMD jobs on a Cray requires manually launching the jobs, as opposed to utilizing a built in Chapel launcher. Support for launching SPMD jobs with the built-in Chapel launchers will be added in the future.
Multilocale Mode¶
Multilocale mode is where both Chapel and MPI communications may be mixed. This allows the user to use optimized/convenient MPI routines when desired, while having access to the Chapel PGAS model. Using this model requires
The MPI library should (and in many cases must) support the
MPI_THREAD_MULTIPLE
support level for threads. This is needed if the user plans on making MPI calls from multiple threads. It is necessary when using the mpi-conduit for GASNet, since the GASNet library may make simultaneous MPI calls. We’ve had good experience with MPICH andMPI_THREAD_MULTIPLE
.
Setting up multilocale mode on a Cray:
The recommended configuration for running multilocale MPI jobs on a Cray is as follows:
CHPL_TARGET_COMPILER=cray-prgenv-{gnu, intel}
CHPL_TASKS={qthreads, fifo} # see discussion below
CHPL_COMM={ugni, gasnet}
CHPL_COMM_SUBSTRATE={aries, mpi} # if CHPL_COMM=gasnet
MPICH_MAX_THREAD_SAFETY=multiple
AMMPI_MPI_THREAD=multiple # if CHPL_COMM_SUBSTRATE=mpi
Running under gasnet+aries
might require setting MPICH_GNI_DYNAMIC_CONN=disabled
.
This is discussed here.
These are the configurations in which this module is currently tested. Any launcher should work fine for this mode. Support is expected to expand in future versions.
Qthreads and MPI¶
Since MPI is not natively Qthread-aware, some care is required to avoid deadlocks. This
section describes current recommendations on using CHPL_TASKS=qthreads
and the MPI
module.
We assume that CHPL_COMM
is either ugni
or gasnet+aries
.
We do not recommend using the MPI module with the gasnet+mpi
communication backend
and qthreads
.
Use non-blocking calls whenever possible. Note that this also requires using
MPI_Test
instead ofMPI_Wait
. For convenience, we provide wrappers for a subset of the MPI blocking calls that are implemented with non-blocking calls and correctly yield tasks while waiting.Any blocking calls (including third-party libraries) must be preceded with a call to
Barrier
.Blocking calls must be serialized; concurrent blocking calls can result in deadlocks.
Configurations Constants¶
This module uses two boolean config constants:
autoInitMPI
and requireThreadedMPI
.
Refer to their documentation for more information on when to use them.
Communicators¶
The GASNet runtime, and therefore Chapel, makes no guarantees that the MPI
ranks will match the GASNet locales. This module creates a new MPI communicator
CHPL_COMM_WORLD
that ensures that this mapping is true.
Note that if numLocales is 1, CHPL_COMM_WORLD
is identical to MPI_COMM_WORLD
,
which is the desired behaviour for SPMD mode programs.
Note
Pointer arguments are written as
ref
arguments, so no casting to ac_ptr
is necessary.An exception to the above is if the C prototype names the argument
array_of_*
, in which case it is written using an array form.Some MPI-1.1 functions were deprecated in MPI-2. These should be updated in the future, but are still present in this version.
MPI_Aint
is represented by ptrdiff. If this is not the correct size, there will be an assertion failure in the code.
MPI Module Documentation¶
Note
For items without documentation, please refer to the MPI documentation.
- config const autoInitMPI = true¶
Automatically initializes MPI (if not already initialized by the runtime), and shuts it down as well.
- config const requireThreadedMPI = true¶
Ensures that MPI is running in
MPI_THREAD_MULTIPLE
mode, and will abort if not. This is not necessary if you are running SPMD mode, but is likely to be necessary if you run in multilocale mode.
- proc CHPL_COMM_WORLD¶
Define a new communicator that directly maps to Chapel locales. This is just a reordering of
MPI_COMM_WORLD
, which you are, of course, free to continue to use. This just guarantees that locale ids and MPI ranks agree.
- proc initialize()¶
Helper routine that also sets process IDs (world rank) and number of processes (world size)
- proc commRank(comm: MPI_Comm = MPI_COMM_WORLD): c_int¶
Wrapper to get the rank of the communicator comm. Defaults to MPI_COMM_WORLD, if no communicator is passed in.
- proc commSize(comm: MPI_Comm = MPI_COMM_WORLD): c_int¶
Wrapper to get the size of the communicator comm. Defaults to MPI_COMM_WORLD, if no communicator is passed in.
- proc Wait(ref request: MPI_Request, ref status: MPI_Status): c_int¶
Drop in replacement for MPI_Wait, implemented with non-blocking MPI calls.
This is simply implemented as a while loop that continually calls
MPI_Test
. The loop will yield, allowing other tasks to run.
- proc Wait(ref request: MPI_Request): c_int
Overloaded version of Wait, which ignores the returned status
- proc Barrier(comm: MPI_Comm): c_int¶
Drop in replacement for
MPI_Barrier
, with non-blocking MPI calls.This is implemented by a call to
MPI_Ibarrier
, followed by a call toWait
above. The returned value ofMPI_Status
is ignored.
- proc Send(ref buf, count: c_int, datatype: MPI_Datatype, dest: c_int, tag: c_int, comm: MPI_Comm): c_int¶
Drop in replacement for
MPI_Send
, with non-blocking MPI calls.This is implemented by a call to
MPI_Isend
, followed by a call toWait
above. The returned value ofMPI_Status
is ignored.
- proc Recv(ref buf, count: c_int, datatype: MPI_Datatype, source: c_int, tag: c_int, comm: MPI_Comm, ref status: MPI_Status): c_int¶
Drop in replacement for
MPI_Recv
, with non-blocking MPI calls.This is implemented by a call to
MPI_Irecv
, followed by a call toWait
above. The returned value ofMPI_Status
is ignored.
- record MPI_Status¶
A wrapper around
MPI_Status
. Only the defined fields are exposed- var MPI_SOURCE: c_int¶
- var MPI_TAG: c_int¶
- var MPI_ERROR: c_int¶
- proc ref MPI_Status.getCount(tt: MPI_Datatype)¶
Get the count from a status object
- type MPI_Aint = c_ptrdiff¶
- type MPI_Group¶
- type MPI_Comm¶
- type MPI_Datatype¶
- type MPI_Request¶
- type MPI_Op¶
- const MPI_THREAD_SINGLE: c_int¶
- const MPI_THREAD_FUNNELED: c_int¶
- const MPI_THREAD_SERIALIZED: c_int¶
- const MPI_THREAD_MULTIPLE: c_int¶
- type MPI_Errhandler = opaque¶
- const MPI_SUCCESS: c_int¶
- const MPI_ERR_BUFFER: c_int¶
- const MPI_ERR_COUNT: c_int¶
- const MPI_ERR_TYPE: c_int¶
- const MPI_ERR_TAG: c_int¶
- const MPI_ERR_COMM: c_int¶
- const MPI_ERR_RANK: c_int¶
- const MPI_ERR_REQUEST: c_int¶
- const MPI_ERR_ROOT: c_int¶
- const MPI_ERR_GROUP: c_int¶
- const MPI_ERR_OP: c_int¶
- const MPI_ERR_TOPOLOGY: c_int¶
- const MPI_ERR_DIMS: c_int¶
- const MPI_ERR_ARG: c_int¶
- const MPI_ERR_UNKNOWN: c_int¶
- const MPI_ERR_TRUNCATE: c_int¶
- const MPI_ERR_OTHER: c_int¶
- const MPI_ERR_INTERN: c_int¶
- const MPI_PENDING: c_int¶
- const MPI_ERR_IN_STATUS: c_int¶
- const MPI_ERR_LASTCODE: c_int¶
- const MPI_BOTTOM: opaque¶
- const MPI_PROC_NULL: opaque¶
- const MPI_ANY_SOURCE: opaque¶
- const MPI_ANY_TAG: opaque¶
- const MPI_UNDEFINED: opaque¶
- const MPI_BSEND_OVERHEAD: opaque¶
- const MPI_KEYVAL_INVALID: opaque¶
- const MPI_ERRORS_ARE_FATAL: MPI_Errhandler¶
- const MPI_ERRORS_RETURN: MPI_Errhandler¶
- const MPI_MAX_PROCESSOR_NAME: c_int¶
- const MPI_MAX_ERROR_STRING: c_int¶
- const MPI_CHAR: MPI_Datatype¶
- const MPI_SHORT: MPI_Datatype¶
- const MPI_INT: MPI_Datatype¶
- const MPI_LONG: MPI_Datatype¶
- const MPI_UNSIGNED_CHAR: MPI_Datatype¶
- const MPI_UNSIGNED_SHORT: MPI_Datatype¶
- const MPI_UNSIGNED: MPI_Datatype¶
- const MPI_UNSIGNED_LONG: MPI_Datatype¶
- const MPI_FLOAT: MPI_Datatype¶
- const MPI_DOUBLE: MPI_Datatype¶
- const MPI_LONG_DOUBLE: MPI_Datatype¶
- const MPI_BYTE: MPI_Datatype¶
- const MPI_PACKED: MPI_Datatype¶
- const MPI_FLOAT_INT: MPI_Datatype¶
- const MPI_DOUBLE_INT: MPI_Datatype¶
- const MPI_LONG_INT: MPI_Datatype¶
- const MPI_2INT: MPI_Datatype¶
- const MPI_SHORT_INT: MPI_Datatype¶
- const MPI_LONG_DOUBLE_INT: MPI_Datatype¶
- const MPI_LONG_LONG_INT: MPI_Datatype¶
- const MPI_UB: MPI_Datatype¶
- const MPI_LB: MPI_Datatype¶
- const MPI_COMM_WORLD: MPI_Comm¶
- const MPI_COMM_SELF: MPI_Comm¶
- const MPI_COMM_NULL: MPI_Comm¶
- const MPI_IDENT: c_int¶
- const MPI_CONGRUENT: c_int¶
- const MPI_SIMILAR: c_int¶
- const MPI_UNEQUAL: c_int¶
- const MPI_TAG_UB: c_int¶
- const MPI_IO: c_int¶
- const MPI_HOST: c_int¶
- const MPI_WTIME_IS_GLOBAL: c_int¶
- const MPI_MAX: MPI_Op¶
- const MPI_MIN: MPI_Op¶
- const MPI_SUM: MPI_Op¶
- const MPI_PROD: MPI_Op¶
- const MPI_MAXLOC: MPI_Op¶
- const MPI_MINLOC: MPI_Op¶
- const MPI_BAND: MPI_Op¶
- const MPI_BOR: MPI_Op¶
- const MPI_BXOR: MPI_Op¶
- const MPI_LAND: MPI_Op¶
- const MPI_LOR: MPI_Op¶
- const MPI_LXOR: MPI_Op¶