Topology

C | Fortran-2008 | Fortran-90

MPI_Comm_create

Definition

MPI_Comm_create allows MPI processes in a given communicator to create a communicator per group. In other words, for MPI processes that belong to a given communicator while residing in different groups, a call to MPI_Comm_create creates distinct communicators; one for each group. Note: the groups specified must be disjoint.
If an MPI process passes a group argument specifying a group it does not belong to, MPI_COMM_NULL is returned. For MPI processes that do not belong to a group, MPI_GROUP_EMPTY can be passed as the group argument.

Copy

Feedback

int MPI_Comm_create(MPI_Comm old_communicator,
                    MPI_Group group,
                    MPI_Comm* new_communicator);

Parameters

old_communicator

The communicator from which the group of processes is extracted.

group

The group containing the processes from the old_communicator to include in the new communicator. It can contain the entire group of processes of the old communicator, or just a subgroup.

new_communicator

The variable in which store the communicator created. If the calling process is not part of the communicator created, MPI_COMM_NULL is stored instead.

Return value

The error code returned from the communicator creation.

Example

Copy

Feedback

#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>

/**
 * @brief Illustrates how to create a communicators from groups using
 * MPI_Comm_create.
 * @details In this example, 6 MPI processes are split as follows:
 * +------+---------+---------+----------+
 * | Rank | Group A | Group B | No group |
 * +------+---------+---------+----------+
 * |   0  |    X    |         |          |
 * |   1  |    X    |         |          |
 * |   2  |    X    |         |          |
 * |   3  |         |    X    |          |
 * |   4  |         |    X    |          |
 * |   5  |         |         |     X    |
 * +------+---------+---------+----------+
 * These MPI processes, which form 3 disjoint groups, belong to the same
 * communicator. These 6 MPI processes will call MPI_Comm_create so that each
 * group gets its own communicator. Finally, they will get their rank in their
 * new communicator before sending it back to the MPI process having received
 * the rank 0 in that new communicator.
 * This application is meant to be run with 6 processes.
 **/
int main(int argc, char* argv[])
{
    MPI_Init(&argc, &argv);

    // Check that the application is run with 6 processes.
    int size;
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    if(size != 6)
    {
        printf("Please run this application with 6 MPI processes.\n");
        MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
    }

    // Get my rank in the global communicator
    int my_rank_global;
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank_global);

    // Get the group or processes of the default communicator
    MPI_Group world_group;
    MPI_Comm_group(MPI_COMM_WORLD, &world_group);

    // Create the new communicator from that group of processes.
    MPI_Comm local_communicator;

    if(my_rank_global == 0 ||
       my_rank_global == 1 ||
       my_rank_global == 2)
    {
        // Keep MPI processes 0, 1, 2 in a group we will call group A.
        int group_a_ranks[3] = {0, 1, 2};
        MPI_Group group_a;
        MPI_Group_incl(world_group, 3, group_a_ranks, &group_a);
        MPI_Comm_create(MPI_COMM_WORLD, group_a, &local_communicator);
    }
    else if(my_rank_global == 3 ||
            my_rank_global == 4)
    {
        // Keep MPI processes 3 and 4 in a group we will call group B.
        int group_b_ranks[2] = {3, 4};
        MPI_Group group_b;
        MPI_Group_incl(world_group, 2, group_b_ranks, &group_b);
        MPI_Comm_create(MPI_COMM_WORLD, group_b, &local_communicator);
    }
    else
    {
        // Only MPI process 5 remains, without a group
        MPI_Comm_create(MPI_COMM_WORLD, MPI_GROUP_EMPTY, &local_communicator);
    }

    // Check if I got into a new communicator (that is, if I was in a group to begin with)
    if(local_communicator == MPI_COMM_NULL)
    {
        // I am not part of the new communicator, I can't participate to that broadcast.
        printf("MPI process %d was not part of any group, thus did not get into a new communicator.\n", my_rank_global);

        // Let's wait all processes before proceeding to the second phase; Cleaner output.
        MPI_Barrier(MPI_COMM_WORLD);
    }
    else
    {
        // Get my rank local to the new communicator
        int my_rank_local;
        MPI_Comm_rank(local_communicator, &my_rank_local);

        printf("MPI process %d in global communicator has now rank %d in new communicator.\n", my_rank_global, my_rank_local);

        // Let's wait all processes before proceeding to the second phase; Cleaner output.
        MPI_Barrier(MPI_COMM_WORLD);
            
        int size_local_communicator;
        MPI_Comm_size(local_communicator, &size_local_communicator);

        // The MPI process that got assigned rank 0 in each new communicator will gather all ranks in that communicator and display them
        int global_ranks_in_local_communicator[size_local_communicator];
        MPI_Gather(&my_rank_global,
                   1,
                   MPI_INT,
                   global_ranks_in_local_communicator,
                   1,
                   MPI_INT,
                   0,
                   local_communicator);

        if(my_rank_local == 0)
        {
            printf("MPI processes ");
            for(int i = 0; i < size_local_communicator; i++)
            {
                if(i > 0)
                {
                    printf(" and ");
                }
                printf("%d", global_ranks_in_local_communicator[i]);
            }
            printf(" are in the same new communicator.\n");
        }
    }

    MPI_Finalize();

    return EXIT_SUCCESS;
}