Use cases for MPI communicator handles in CCA
The primary parallel context in MPI-based codes is defined by a communicator. Here are the two basic use-cases for a component to end up with a communicator.
In component-oriented programming, use of global resource (MPI_COMM_WORLD) is incorrect. This leaves the component developer with the task of initializing the communicator (or just rank information) used in a parallel algorithm implementation.
Case 0: Just want to know which process this is
To properly handle parallel data during local computations, many components in parallel programs need only the rank and size of a communicator and do not need message passing. An example is any component which wants rank just for output files or for issuing error messages.
Case 1: Get it from somewhere
In many cases, the component implementor does not need to expose to callers the fact that internally MPI is used. In this case, the component writer can call on a well-known (service) port during the setServices call to get a unique (not shared with other components) communicator. In a simple SPMD computing model, the framework instance which runs in parallel on all processes can provide the needed communicator handle during setServices. In the MCMD model, the application framer may need to substitute other sources of MPIService and make connections according to their desired process groups decomposition.
MPIService is proposed to handle this case. As all (at least before the advent of MPI-2) MCMD MPI applications run SPMD until the program logic splits a communicator, the solution is potentially applicable to any MPI-based component.
Case 2: Expect it to be set from somewhere
In many cases, the component implementors choose to expose the dependency on caller-provided communicator. This communicator is usually passed during an initialization call. The component implementation may or may not allow for the communicator given to be shared with other components in the same process. The component implementation may need more than one communicator, e.g. a second one for file I/O processes. As the variety of particular circumstances is large, no formal standard is proposed for the "set communicator" case. For components not requiring complex initialization, we suggest
/** Collective call to specify the communicator this component needs. @param fComm Fortran form of the communicator. */ int setMPIComm(in long fComm);
For components with the typical HPC lifecycle and a complex setup
initialize(... lots of arguments...) compute(...) finish(...)
we recommend passing the communicator in the argument list of initialize to better ensure consistency.