8. Communicator Subgroups

The MPI_Comm_split function is used to split an existing communicator into subgroups based on color and key values, which these subgroups of processes need to work together. Processes with the same color are placed in the same subgroup, and within each subgroup, they are ordered based on their key values. The new communicator (newcomm) is created, representing the subgroup, and each process in the subgroup is assigned a rank within this new communicator.

int MPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm *newcomm);
  • comm: The input communicator (existing MPI communicator).

  • color: An integer value that determines the color of the subgroups. Processes with the same color value will be placed in the same subgroup.

  • key: An integer value used to order the processes within a subgroup. Processes with the same color are ordered based on their key values.

  • newcomm: A pointer to the new communicator that is returned.

When a communicator is no longer actively used, it is advisable to release its resources by calling MPI_Comm_free. This avoids potential memory leaks in MPI programs.

int MPI_Comm_free(MPI_Comm *comm);

Example:

In the following example, the code splits the communicator MPI_COMM_WORLD into two subgroups based on even and odd ranks and at the end frees the newly created communicators.

#include <mpi.h>
#include <iostream>

int main(int argc, char** argv) {
  MPI_Init(&argc, &argv);

  int rank, size;
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &size);

  // Determine color based on even or odd rank
  int color = rank % 2;

  // Split the communicator based on color
  MPI_Comm new_comm;
  MPI_Comm_split(MPI_COMM_WORLD, color, rank, &new_comm);

  int new_rank, new_size;
  MPI_Comm_rank(new_comm, &new_rank);
  MPI_Comm_size(new_comm, &new_size);

  // Print information about the original and new communicators
  std::cout << "Rank " << rank << " out of " << size << " in MPI_COMM_WORLD, " \
            << "New Rank " << new_rank << " out of " << new_size << " in new_comm, " \
            << "Subgroup " << color << std::endl;


  MPI_Comm_free(&new_comm);

  MPI_Finalize();
  return 0;
}
MPI_Comm_split

Fig 8.1. Splitting the default communicator into four distinct subgroups.

Task

  1. Write a C/C++ code that splits the default communicator into four different subgroups based on the current rank.

  2. You can assume that the total number of created processes should be divisible by 4.

  3. If we have 16 processes, the first communicator has processes [0, 1, 2, 3], the second communicator has processes [4, 5, 6, 7] and so on (like Fig.8.1).

  4. Your code should print the old rank, new rank, the old communicator, and the new subgroup in the new communicator.

  5. Use a batch file to run your code with 16 processes and provide the output of your job.