% Version of 4/27/95 % Version of bind that does not put ``int'' first \def\mpibindA#1{{\raggedright \hangindent 7em\hangafter=1\tt #1 \par \vspace{0.1in}}} %\def\comm{comm} %\def\Comm{Communicator} %\begin{document} \chapter{MPI Environmental Management} \label{sec:environment} \label{chap:environment} This chapter discusses routines for getting and, where appropriate, setting various parameters that relate to the \MPI/ implementation and the execution environment (such as error handling). The procedures for entering and leaving the \MPI/ execution environment are also described here. \section{Implementation information} \label{sec:inquiry-impl} \subsection{Environmental Inquiries} \label{subsec:inquiry-inquiry} A set of attributes that describe the execution environment are attached to the communicator \const{MPI\_COMM\_WORLD} when \MPI/ is initialized. The value of these attributes can be inquired by using the function \mpifunc{MPI\_ATTR\_GET} described in Chapter~\ref{chap:context}. It is erroneous to delete these attributes, \snir free their keys, or change their values. \rins The list of predefined attribute keys include \begin{description} \item[\const{MPI\_TAG\_UB}] Upper bound for tag value. \item[\const{MPI\_HOST}] Host process rank, if such exists, \const{MPI\_PROC\_NULL}, otherwise. \item[\const{MPI\_IO}] rank of a node that has regular I/O facilities (possibly myrank). Nodes in the same communicator may return different values for this parameter. \snir \item[\const{MPI\_WTIME\_IS\_GLOBAL}] Boolean variable that indicates whether clocks are synchronized. \rins \end{description} Vendors may add implementation specific parameters (such as node number, real memory size, virtual memory size, etc.) \snir These predefined attributes do not change value between \MPI/ initialization (\mpifunc{MPI\_INIT} and \MPI/ completion (\mpifunc{MPI\_FINALIZE}), and cannot be updated or deleted by users. \begin{users} Note that in the C binding, the value returned by these attributes is a {\em pointer} to an \code{int} containing the requested value. \end{users} \rins The required parameter values are discussed in more detail below: \subsubsection{Tag values} Tag values range from \code{0} to the value returned for \const{MPI\_TAG\_UB} inclusive. These values are guaranteed to be unchanging during the execution of an \MPI/ program. In addition, the tag upper bound value must be {\em at least\/} 32767. An \MPI/ implementation is free to make the value of \const{MPI\_TAG\_UB} larger than this; for example, the value \(2^{30}-1\) is also a legal value for \const{MPI\_TAG\_UB}. \snir The attribute \const{MPI\_TAG\_UB} has the same value on all processes of \const{MPI\_COMM\_WORLD}. \rins \subsubsection{Host rank} The value returned for \const{MPI\_HOST} gets the rank of the {\tt HOST} process in the group associated with communicator \const{MPI\_COMM\_WORLD}, if there is such. \const{MPI\_PROC\_NULL} is returned if there is no host. \MPI/ does not specify what it means for a process to be a {\tt HOST}, nor does it requires that a {\tt HOST} exists. \snir The attribute \const{MPI\_HOST} has the same value on all processes of \const{MPI\_COMM\_WORLD}. \rins \subsubsection{IO rank} The value returned for \const{MPI\_IO} is the rank of a processor that can provide language-standard I/O facilities. For Fortran, this means that all of the Fortran I/O operations are supported (e.g., {\tt OPEN}, {\tt REWIND}, {\tt WRITE}). For C, this means that all of the ANSI-C I/O operations are supported (e.g., {\tt fopen}, {\tt fprintf}, {\tt lseek}). \snir If every process can provide language-standard I/O, then the value \const{MPI\_ANY\_SOURCE} will be returned. Otherwise, if the calling process can provide language-standard I/O, then its rank will be returned. Otherwise, if some process can provide language-standard I/O then the rank of one such process will be returned. The same value need not be returned by all processes. If no process can provide language-standard I/O, then the value \const{MPI\_PROC\_NULL} will be %mansplit returned. \begin{users} Note that input is not collective, and this attribute does {\em not} indicate which process can or does provide input. \end{users} \subsubsection{Clock synchronization} The value returned for \const{MPI\_WTIME\_IS\_GLOBAL} is 1 if clocks at all processes in \linebreak \const{MPI\_COMM\_WORLD} are synchronized, 0 otherwise. A collection of clocks is considered synchronized if explicit effort has been taken to synchronize them. The expectation is that the variation in time, as measured by calls to \mpifunc{MPI\_WTIME}, will be less then one half the round-trip time for an \MPI/ message of length zero. If time is measured at a process just before a send and at another process just after a matching receive, the second time should be always higher than the first one. The attribute \const{MPI\_WTIME\_IS\_GLOBAL} need not be present when the clocks are not synchronized (however, the attribute key \const{MPI\_WTIME\_IS\_GLOBAL} is always valid). This attribute may be associated with communicators other then \const{MPI\_COMM\_WORLD}. The attribute \const{MPI\_WTIME\_IS\_GLOBAL} has the same value on all processes of \const{MPI\_COMM\_WORLD}. \rins \begin{funcdef}{MPI\_GET\_PROCESSOR\_NAME( name, resultlen )} \funcarg{\OUT}{name}{A unique specifier for the actual (as opposed to virtual) node.} \funcarg{\OUT}{resultlen}{Length (in printable characters) of the result returned in \code{name}} \end{funcdef} \mpibind{MPI\_Get\_processor\_name(char~*name, int~*resultlen)} \mpifbind{MPI\_GET\_PROCESSOR\_NAME( NAME, RESULTLEN, IERROR)\fargs CHARACTER*(*) NAME\\INTEGER RESULTLEN,IERROR} This routine returns the name of the processor on which it was called at the moment of the call. The name is a character string for maximum flexibility. From this value it must be possible to identify a specific piece of hardware; possible values include ``processor 9 in rack 4 of mpp.cs.org'' and ``231'' (where 231 is the actual processor number in the running homogeneous system). The argument \mpiarg{name} must represent storage that is at least \const{MPI\_MAX\_PROCESSOR\_NAME} characters long. \func{MPI\_GET\_PROCESSOR\_NAME} may write up to this many characters into \mpiarg{name}. The number of characters actually written is returned in the output argument, \mpiarg{resultlen}. \begin{rationale} This function allows \MPI/ implementations that do process migration to return the current processor. Note that nothing in \MPI/ {\em requires} or defines process migration; this definition of \mpifunc{MPI\_GET\_PROCESSOR\_NAME} simply allows such an implementation. \end{rationale} \begin{users} The user must provide at least \const{MPI\_MAX\_PROCESSOR\_NAME} space to write the processor name --- processor names can be this long. The user should examine the ouput argument, \mpiarg{resultlen}, to determine the actual length of the name. \end{users} \snir The constant \const{MPI\_BSEND\_OVERHEAD} provides an upper bound on the fixed overhead per message buffered by a call to \mpifunc{MPI\_BSEND} (see Section~\ref{subsec:pt2pt-modelbuffered}). \rins \section{Error handling} \label{sec:inquiry-error} An \MPI/ implementation cannot or may choose not to handle some errors that occur during \MPI/ calls. These can include errors that generate exceptions or traps, such as floating point errors or access violations. The set of errors that are handled by \MPI/ is implementation-dependent. Each such error generates an {\bf MPI exception}. \snir The above text takes precedence over any text on error handling within this document. Specifically, text that states that errors {\em will} be handled should be read as {\em may} be handled. \rins A user can associate an error handler with a communicator. The specified error handling routine will be used for any \MPI/ exception that occurs during a call to \MPI/ for a communication with this communicator. \MPI/ calls that are not related to any communicator are considered to be attached to the communicator \const{MPI\_COMM\_WORLD}. The attachment of error handlers to communicators is purely local: different processes may attach different error handlers to the same communicator. A newly created communicator inherits the error handler that is associated with the ``parent'' communicator. In particular, the user can specify a ``global'' error handler for all communicators by associating this handler with the communicator \const{MPI\_COMM\_WORLD} immediately after initialization. Several predefined error handlers are available in \MPI/: \begin{description} \item[\const{MPI\_ERRORS\_ARE\_FATAL}] The handler, when called, causes the program to abort on all executing processes. This has the same effect as if \mpifunc{MPI\_ABORT} was called by the process that invoked the handler. \item[\const{MPI\_ERRORS\_RETURN}] The handler has no effect \snir other than returning the error code to the user. \rins \end{description} Implementations may provide additional predefined error handlers and programmers can code their own error handlers. The error handler \const{MPI\_ERRORS\_ARE\_FATAL} is associated by default with \const{MPI\_COMM-} \const{\_WORLD} %mansplit after initialization. Thus, if the user chooses not to control error handling, every error that \MPI/ handles is treated as fatal. Since (almost) all \MPI/ calls return an error code, a user may choose to handle errors in its main code, by testing the return code of \MPI/ calls and executing a suitable recovery code when the call was not successful. In this case, the error handler \const{MPI\_ERRORS\_RETURN} will be used. Usually it is more convenient and more efficient not to test for errors after each \MPI/ call, and have such error handled by a non trivial \MPI/ error handler. After an error is detected, the state of \MPI/ is undefined. That is, using a user-defined error handler, or \const{MPI\_ERRORS\_RETURN}, does {\em not\/} necessarily allow the user to continue to use \MPI/ after an error is detected. The purpose of these error handlers is to allow a user to issue user-defined error messages and to take actions unrelated to \MPI/ (such as flushing I/O buffers) before a program exits. An \MPI/ implementation is free to allow \MPI/ to continue after an error but is not required to do so. \begin{implementors} A good quality implementation will, to the greatest possible, extent, circumscribe the impact of an error, so that normal processing can continue after an error handler was invoked. The implementation documentation will provide information on the possible effect of each class of errors. \end{implementors} An \MPI/ error handler is an opaque object, which is accessed by a handle. \MPI/ calls are provided to create new error handlers, to associate error handlers with communicators, and to test which error handler is associated with a communicator. \begin{funcdef}{MPI\_ERRHANDLER\_CREATE( function, errhandler )} \funcarg{\IN}{function}{user defined error handling procedure} \funcarg{\OUT}{errhandler}{MPI error handler (handle)} \end{funcdef} \mpibind{MPI\_Errhandler\_create(MPI\_Handler\_function~*function, MPI\_Errhandler~*errhandler)} \mpifbind{MPI\_ERRHANDLER\_CREATE(FUNCTION, HANDLER, IERROR)\fargs EXTERNAL FUNCTION \\ INTEGER ERRHANDLER, IERROR} Register the user routine \mpiarg{function} for use as an \MPI/ exception handler. Returns in \mpiarg{errhandler} a handle to the registered exception handler. % % This is not true because of the reference count AND the effect of % errhandler_free. %\begin{implementors} %The handle returned may contain the address of the error handling routine. %This call is superfluous in C, which has a referencing operator, but is %necessary in Fortran. %\end{implementors} % % \snir In the C language, \rins the user routine should be a C function of type \const{MPI\_Handler\_function}, which is defined as: \begin{verbatim} typedef void (MPI_Handler_function)(MPI_Comm *, int *, ...); \end{verbatim} The first argument is the communicator in use. \snir The second is the error code to be returned by the \MPI/ routine that raised the error. If the routine would have returned \const{MPI\_ERR\_IN\_STATUS}, it is the error code returned in the status for the request that caused the error handler to be invoked. \rins The remaining arguments are ``\code{stdargs}'' arguments whose number and meaning is implementation-dependent. An implementation should clearly document these arguments. Addresses are used so that the handler may be written in Fortran. % if the args are implementation dependent, it doesn't mean they are variable % or "stdargs" !!!! \begin{rationale} The variable argument list is provided because it provides an ANSI-standard hook for providing additional information to the error handler; without this hook, ANSI C prohibits additional arguments. \end{rationale} \begin{funcdef}{MPI\_ERRHANDLER\_SET( comm, errhandler )} \funcarg{\IN}{comm}{communicator to set the error handler for (handle)} \funcarg{\IN}{errhandler}{new MPI error handler for communicator (handle)} \end{funcdef} \mpibind{MPI\_Errhandler\_set(MPI\_Comm~comm, MPI\_Errhandler~errhandler)} \mpifbind{MPI\_ERRHANDLER\_SET(COMM, ERRHANDLER, IERROR)\fargs INTEGER COMM, ERRHANDLER, IERROR} Associates the new error handler \mpiarg{errorhandler} with communicator \mpiarg{comm} at the calling process. Note that an error handler is always associated with the communicator. \begin{funcdef}{MPI\_ERRHANDLER\_GET( comm, errhandler )} \funcarg{\IN}{comm}{communicator to get the error handler from (handle)} \funcarg{\OUT}{errhandler}{MPI error handler currently associated with communicator (handle)} \end{funcdef} \mpibind{MPI\_Errhandler\_get(MPI\_Comm~comm, MPI\_Errhandler~*errhandler)} \mpifbind{MPI\_ERRHANDLER\_GET(COMM, ERRHANDLER, IERROR)\fargs INTEGER COMM, ERRHANDLER, IERROR} Returns in \mpiarg{errhandler} (a handle to) the error handler that is currently associated with communicator \mpiarg{comm}. Example: A library function may register at its entry point the current error handler for a communicator, set its own private error handler for this communicator, and restore before exiting the previous error handler. \begin{funcdef}{MPI\_ERRHANDLER\_FREE( errhandler )} \funcarg{\IN}{errhandler}{MPI error handler (handle)} \end{funcdef} \mpibind{MPI\_Errhandler\_free(MPI\_Errhandler~*errhandler)} \mpifbind{MPI\_ERRHANDLER\_FREE(ERRHANDLER, IERROR)\fargs INTEGER ERRHANDLER, IERROR} Marks the error handler associated with \mpiarg{errhandler} for deallocation and sets \mpiarg{errhandler} to \const{MPI\_ERRHANDLER\_NULL}. The error handler will be deallocated after all communicators associated with it have been deallocated. \begin{funcdef}{MPI\_ERROR\_STRING( errorcode, string, resultlen )} \funcarg{\IN}{errorcode}{Error code returned by an MPI routine} \funcarg{\OUT}{string}{Text that corresponds to the \const{errorcode}} \funcarg{\OUT}{resultlen}{Length (in printable characters) of the result returned in \const{string}} \end{funcdef} \mpibind{MPI\_Error\_string(int~errorcode, char~*string, int~*resultlen)} \mpifbind{MPI\_ERROR\_STRING(ERRORCODE, STRING, RESULTLEN, IERROR)\fargs INTEGER ERRORCODE, RESULTLEN, IERROR \\ CHARACTER*(*) STRING} Returns the error string associated with an error code \snir or class. \rins The argument \mpiarg{string} must represent storage that is at least \const{MPI\_MAX\_ERROR\_STRING} characters long. The number of characters actually written is returned in the output argument, \mpiarg{resultlen}. \begin{rationale} The form of this function was chosen to make the Fortran and C bindings similar. A version that returns a pointer to a string has two difficulties. First, the return string must be statically allocated and different for each error message (allowing the pointers returned by successive calls to \const{MPI\_ERROR\_STRING} to point to the correct message). Second, in Fortran, a function declared as returning \const{CHARACTER*(*)} can not be referenced in, for example, a \const{PRINT} statement. \end{rationale} \section{Error codes and classes} The error codes returned by \MPI/ are left entirely to the implementation (with the exception of \const{MPI\_SUCCESS}). This is done to allow an implementation to provide as much information as possible in the error code (for use with \mpifunc{MPI\_ERROR\_STRING}). To make it possible for an application to interpret an error code, the routine \mpifunc{MPI\_ERR-} \func{OR\_CLASS} %mansplit \snir converts any error code into one of a small set of standard error codes, called {\em error classes}. Valid error classes include \begin{center} \begin{tabular}{ll} \const{MPI\_SUCCESS} &No error \\ \const{MPI\_ERR\_BUFFER} &Invalid buffer pointer \\ \const{MPI\_ERR\_COUNT} &Invalid count argument \\ \const{MPI\_ERR\_TYPE} &Invalid datatype argument \\ \const{MPI\_ERR\_TAG} &Invalid tag argument \\ \const{MPI\_ERR\_COMM} &Invalid communicator\\ \const{MPI\_ERR\_RANK} &Invalid rank \\ \const{MPI\_ERR\_REQUEST} &Invalid request (handle)\\ \const{MPI\_ERR\_ROOT} &Invalid root \\ \const{MPI\_ERR\_GROUP} &Invalid group\\ \const{MPI\_ERR\_OP} &Invalid operation \\ \const{MPI\_ERR\_TOPOLOGY} &Invalid topology \\ \const{MPI\_ERR\_DIMS} &Invalid dimension argument \\ \const{MPI\_ERR\_ARG} &Invalid argument of some other kind \\ \const{MPI\_ERR\_UNKNOWN} &Unknown error \\ \const{MPI\_ERR\_TRUNCATE} &Message truncated on receive\\ \const{MPI\_ERR\_OTHER} &Known error not in this list\\ \const{MPI\_ERR\_INTERN} &Internal MPI (implementation) error\\ \const{MPI\_ERR\_IN\_STATUS} &Error code is in status\\ \const{MPI\_ERR\_PENDING} &Pending request\\ \const{MPI\_ERR\_LASTCODE} &Last error code\\ \end{tabular} \end{center} The error classes are a subset of the error codes: an \MPI/ function may return an error class number; and the function \mpifunc{MPI\_ERROR\_STRING} can be used to compute the error string associated with an error class. The error codes satisfy, $$ 0 = \const{MPI\_SUCCESS} < \const{MPI\_ERR\_...} \leq \const{MPI\_ERR\_LASTCODE}. $$ \rins \begin{rationale} The difference between \const{MPI\_ERR\_UNKNOWN} and \const{MPI\_ERR\_OTHER} is that \func{MPI\_ERROR\_STRING} can return useful information about \const{MPI\_ERR\_OTHER}. Note that \const{MPI\_SUCCESS} $= 0$ is necessary to be consistent with C practice; the separation of error classes and error codes allows us to define the error classes this way. Having a known \const{LASTCODE} is often a nice sanity check as well. \end{rationale} \begin{funcdef}{MPI\_ERROR\_CLASS( errorcode, errorclass )} \funcarg{\IN}{errorcode}{Error code returned by an MPI routine} \funcarg{\OUT}{errorclass}{Error class associated with \const{errorcode}} \end{funcdef} \mpibind{MPI\_Error\_class(int~errorcode, int~*errorclass)} \mpifbind{MPI\_ERROR\_CLASS(ERRORCODE, ERRORCLASS, IERROR)\fargs INTEGER ERRORCODE, ERRORCLASS, IERROR} \snir The function \mpifunc{MPI\_ERROR\_CLASS} maps each standard error code (error class) onto itself. \rins \section{Timers and synchronization} \MPI/ defines a timer. A timer is specified even though it is not ``message-passing,'' because timing parallel programs is important in ``performance debugging'' and because existing timers (both in POSIX 1003.1-1988 and 1003.4D 14.1 and in Fortran 90) are either inconvenient or do not provide adequate access to high-resolution timers. \begin{funcdefna}{MPI\_WTIME()} \end{funcdefna} \mpibindnotint{double MPI\_Wtime(void)} \mpifbind{DOUBLE PRECISION MPI\_WTIME()} \func{MPI\_WTIME} returns a floating-point number of seconds, representing elapsed wall-clock time since some time in the past. The ``time in the past'' is guaranteed not to change during the life of the process. The user is responsible for converting large numbers of seconds to other units if they are preferred. This function is portable (it returns seconds, not ``ticks''), it allows high-resolution, and carries no unnecessary baggage. One would use it like this: \snir \begin{verbatim} { double starttime, endtime; starttime = MPI_Wtime(); .... stuff to be timed ... endtime = MPI_Wtime(); printf("That took %f seconds\n",endtime-starttime); } \end{verbatim} \rins The times returned are local to the node that called them. There is no requirement that different nodes return ``the same time.'' (But see also the discussion of \const{MPI\_WTIME\_IS\_GLOBAL}). \begin{funcdefna}{MPI\_WTICK()} \end{funcdefna} \mpibindnotint{double MPI\_Wtick(void)} \mpifbind{DOUBLE PRECISION MPI\_WTICK()} \func{MPI\_WTICK} returns the resolution of \mpifunc{MPI\_WTIME} in seconds. That is, it returns, as a double precision value, the number of seconds between successive clock ticks. For example, if the clock is implemented by the hardware as a counter that is incremented every millisecond, the value returned by \mpifunc{MPI\_WTICK} should be \(10^{-3}\). \section{Startup} \label{sec:inquiry-startup} One goal of \MPI/ is to achieve {\em source code portability}. By this we mean that a program written using \MPI/ and complying with the relevant language standards is portable as written, and must not require any source code changes when moved from one system to another. This explicitly does {\em not\/} say anything about how an \MPI/ program is started or launched from the command line, nor what the user must do to set up the environment in which an \MPI/ program will run. However, an implementation may require some setup to be performed before other \MPI/ routines may be called. To provide for this, \MPI/ includes an initialization routine \mpifunc{MPI\_INIT}. \begin{funcdefna}{MPI\_INIT()} \end{funcdefna} \mpibind{MPI\_Init(int~*argc, char~***argv)} \mpifbind{MPI\_INIT(IERROR)\fargs INTEGER IERROR} This routine must be called before any other \MPI/ routine. It must be called at most once; subsequent calls are erroneous (see \mpifunc{MPI\_INITIALIZED}). All \MPI/ programs must contain a call to \mpifunc{MPI\_INIT}; this routine must be called before any other \MPI/ routine (apart from \code{MPI\_INITIALIZED}) is called. The version for ANSI C accepts the \const{argc} and \const{argv} that are provided by the arguments to \code{main}: \snir \begin{verbatim} int main(argc, argv) int argc; char **argv; { MPI_Init(&argc, &argv); /* parse arguments */ /* main program */ MPI_Finalize(); /* see below */ } \end{verbatim} \rins The Fortran version takes only \const{IERROR}. \snir An MPI implementation is free to require that the arguments in the C binding must be the arguments to \code{main}. \begin{rationale} The command line arguements are provided {\em to} \mpifunc{MPI\_Init} to allow an MPI implementation to use them in initializing the MPI environment. They are passed by reference to allow an MPI implementation to {\em provide} them in environments where the command-line arguments are not provided to \code{main}. \end{rationale} \rins \discuss{Note that POSIX includes a {\em requirement\/} that access to the command line be provided to Fortran programs (see 8.9 in Std 1003.9--1992). \MPI/ implementations that read command-line arguments should insure the the \MPI/ command-line arguments are clearly identified, for example, by prefixing them with \code{-mpi}. Note the use of the {\em address} of \code{argc} and \code{**argv} in the C binding of \mpifunc{MPI\_INIT}. This is to allow \mpifunc{MPI\_INIT} to remove those arguments that it uses from the argument list. } \begin{funcdefna}{MPI\_FINALIZE()} \end{funcdefna} \mpibind{MPI\_Finalize(void)} \mpifbind{MPI\_FINALIZE(IERROR)\fargs INTEGER IERROR} This routines cleans up all \MPI/ state. Once this routine is called, no \MPI/ routine (even \mpifunc{MPI\_INIT}) may be called. The user must ensure that all pending communications involving a process completes before the process calls \mpifunc{MPI\_FINALIZE}. \begin{funcdef}{MPI\_INITIALIZED( flag )} \funcarg{\OUT}{flag}Flag is true if \mpifunc{MPI\_INIT} has been called and false otherwise. \end{funcdef} \mpibind{MPI\_Initialized(int~*flag)} \mpifbind{MPI\_INITIALIZED(FLAG, IERROR)\fargs LOGICAL FLAG \\ INTEGER IERROR} This routine may be used to determine whether \mpifunc{MPI\_INIT} has been called. It is the {\em only} routine that may be called before \mpifunc{MPI\_INIT} is called. \begin{funcdef}{MPI\_ABORT( comm, errorcode )} \funcarg{\IN}{comm}{communicator of tasks to abort} \funcarg{\IN}{errorcode}{error code to return to invoking environment} \end{funcdef} \mpibind{MPI\_Abort(MPI\_Comm~comm, int~errorcode)} \mpifbind{MPI\_ABORT(COMM, ERRORCODE, IERROR)\fargs INTEGER COMM, ERRORCODE, IERROR} This routine makes a ``best attempt'' to abort all tasks in the group of \mpiarg{comm}. This function does not require that the invoking environment take any action with the error code. However, a Unix or POSIX environment should handle this as a \code{return errorcode} from the main program or an \code{abort(errorcode)}. \MPI/ implementations are required to define the behavior of \mpifunc{MPI\_ABORT} at least for a \code{comm} of \const{MPI\_COMM\_WORLD}. \MPI/ implementations may ignore the \code{comm} argument and act as if the \code{comm} was \const{MPI\_COMM\_WORLD}. \begin{rationale} The communicator argument is provided to allow for future extensions of MPI to environments with, for example, dynamic process management. In particular, it allows but does not require an MPI implementation to abort a subset of \const{MPI\_COMM\_WORLD}. \end{rationale} .