Skip to content
rabaukePublic

Repository files navigation

MPL - A message passing library

build-with-openmpi build-with-mpich build-with-IntelMPI License

MPL is a message passing library written in C++17 based on the Message Passing Interface (MPI) standard. Since the C++ API has been dropped from the MPI standard in version 3.1, it is the aim of MPL to provide a modern C++ message passing library for high performance computing.

MPL will neither bring all functions of the C language MPI-API to C++ nor provide a direct mapping of the C API to some C++ functions and classes. The library's focus lies on the MPI core message passing functions, ease of use, type safety, and elegance. The aim of MPL is to provide an idiomatic C++ message passing library without introducing a significant overhead compared to utilizing MPI via its plain C-API. This library is most useful for developers who have at least some basic knowledge of the Message Passing Interface standard and would like to utilize it via a more user-friendly interface in modern C++. Unlike Boost.MPI, MPL does not rely on an external serialization library and has a negligible run-time overhead.

Supported features

MPL requires an MPI 4.1 implementation and uses its large-count interfaces.

MPL gives currently access via a convenient C++ interface to the following features of the Message Passing Interface standard:

  • environmental management (implicit initialization and finalization and timers),
  • point-to-point communication (blocking and non-blocking),
  • collective communication (blocking and non-blocking),
  • derived data types (happens automatically for many custom data types or via the base_struct_builder helper class and the layout classes of MPL),
  • communicator- and group-management,
  • process topologies (cartesian and graph topologies),
  • inter-communicators,
  • dynamic process creation and
  • file i/o.

Currently, the following MPI features are not yet supported by MPL:

  • one-sided communication.

Although MPL covers a subset of the MPI functionality only, it has probably the largest MPI-feature coverage among all alternative C++ interfaces to MPI.

Hello parallel world

MPL is built on top of the Message Passing Interface (MPI) standard. Therefore, MPL shares many concepts known from the MPI standard, e.g., the concept of a communicator. Communicators manage the message exchange between different processes, i.e., messages are sent and received with the help of a communicator.

The MPL environment provides a global default communicator comm_world, which will be used in the following Hello-World program. The program prints out some information about each process:

  • its rank,
  • the total number of processes and
  • the computer's name the process is running on.

If there are two or more processes, a message is sent from process 0 to process 1, which is also printed.

#include <cstdlib>
#include <iostream>
// include MPL header file
#include <mpl/mpl.hpp>

int main() {
  // get a reference to communicator "world"
  const mpl::communicator &comm_world{mpl::environment::comm_world()};
  // each process prints a message containing the processor name, the rank
  // in communicator world and the size of communicator world
  // output may depend on the underlying MPI implementation
  std::cout << "Hello world! I am running on \"" << mpl::environment::processor_name()
            << "\". My rank is " << comm_world.rank() << " out of " << comm_world.size()
            << " processes.\n";
  // if there are two or more processes send a message from process 0 to process 1
  if (comm_world.size() >= 2) {
    if (comm_world.rank() == 0) {
      std::string message{"Hello world!"};
      comm_world.send(message, 1);  // send message to rank 1
    } else if (comm_world.rank() == 1) {
      std::string message;
      comm_world.recv(message, 0);  // receive message from rank 0
      std::cout << "got: \"" << message << "\"\n";
    }
  }
  return EXIT_SUCCESS;
}

Error handling

When a checked MPI call returns an error, MPL reports it as mpl::mpi_error (derived from mpl::error), carrying its code, class and message. Recognized I/O error classes become mpl::io_failure, including outside file operations; other classes from file operations remain mpl::mpi_error.

MPL installs MPI_ERRORS_RETURN when it initializes its environment and wraps MPI_COMM_WORLD and MPI_COMM_SELF, and when it creates or wraps communicators. With external MPI initialization, earlier operations do not initialize the MPL environment or change those handlers; a fatal handler may abort before a call returns. Borrowed mpi_communicator and mpi_inter_communicator adapters change the original handle's handler without restoring it or taking ownership. MPI file and objectless operations can use different handlers; exceptions are possible only if MPI returns an error to MPL.

Error reporting does not guarantee recovery: MPI may not permit continued execution, and other ranks may remain blocked. Cleanup and destructors are best-effort and do not throw. See the error handling documentation for request completion details.

Building and Testing

MPL can be built and tested using standard CMake commands:

cmake -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DMPL_BUILD_EXAMPLES=ON
cmake --build build -j
ctest --test-dir build --output-on-failure

MPICH / hwloc Troubleshooting

When running unit tests or executables directly via mpirun or mpiexec under MPICH on systems with libhwloc GL plugins installed (hwloc_gl.so), MPI initialization may hang in remote, headless, or containerized environments if an unreachable $DISPLAY socket endpoint is queried via XOpenDisplay.

While CTest targets in MPL configure this automatically, when executing binaries directly under MPICH, disable the hwloc OpenGL discovery component by setting:

export HWLOC_COMPONENTS=-gl
# or prepend to direct mpiexec invocations:
HWLOC_COMPONENTS=-gl mpiexec -n 2 ./build/test/test_communicator_send_recv

Documentation

For further documentation see the documentation, the blog posts

the presentation

the book

the workshop material

and the files in the examples directory of the source package.