Tuesday, November 30, 2010

MPI and Cartesian communicators

/* ----------------------------------------------------------------------- */
/*
 * file:        mpi-cart.c
 * compilation: mpicc -Wall -Wextra mpi-cart.c -o mpi-cart
 * invocation:  mpirun -n 8 mpi-cart
 */
/* ----------------------------------------------------------------------- */
/* Studying MPI functions related to the Cartesian topologies */
/* ----------------------------------------------------------------------- */
#include <stdio.h>
#include <stdlib.h>
/* ----------------------------------------------------------------------- */
#include <mpi.h>
/* ----------------------------------------------------------------------- */
typedef struct MPI_Data_s
{
    MPI_Comm comm;
    int size;
    int rank;
    int root;
} MPI_Data;
/* ----------------------------------------------------------------------- */
#define CART2D_NDIMS 2
typedef struct MPI_Cart2D_Data_s
{
    MPI_Data mpi_data;
    int ndims;
    int dims[CART2D_NDIMS];
    int periods[CART2D_NDIMS];
    int coords[CART2D_NDIMS];
} MPI_Cart2D_Data;
/* ----------------------------------------------------------------------- */
#define CART4D_NDIMS 4
typedef struct MPI_Cart4D_Data_s
{
    MPI_Data mpi_data;
    int ndims;
    int dims[CART4D_NDIMS];
    int periods[CART4D_NDIMS];
    int coords[CART4D_NDIMS];
} MPI_Cart4D_Data;
/* ----------------------------------------------------------------------- */
void Create_2D_Subcomms(MPI_Cart4D_Data *cart4d, int *remain_dims,
        MPI_Cart2D_Data *cart2d)
{
    MPI_Cart_sub(cart4d->mpi_data.comm, remain_dims,
            &(cart2d->mpi_data.comm)
    );

    MPI_Comm_size(cart2d->mpi_data.comm, &(cart2d->mpi_data.size));
    MPI_Comm_rank(cart2d->mpi_data.comm, &(cart2d->mpi_data.rank));
    cart2d->mpi_data.root = 0;
    cart2d->ndims = CART2D_NDIMS;
    MPI_Cart_get(cart2d->mpi_data.comm, cart2d->ndims,
            cart2d->dims, cart2d->periods, cart2d->coords);
}
/* ----------------------------------------------------------------------- */
int main(int argc, char **argv)
{
    /* Some variables */
    MPI_Data world;
    MPI_Cart4D_Data cart4d;
    int remain_dims[CART4D_NDIMS];
    MPI_Cart2D_Data cart2d_01, cart2d_12;

    /* Beginning of the program */
    MPI_Init(&argc, &argv);

    /* Fill-in MPI_COMM_WORLD data */
    world.comm = MPI_COMM_WORLD;
    MPI_Comm_size(world.comm, &(world.size));
    MPI_Comm_rank(world.comm, &(world.rank));
    world.root = 0;

    /* Create a division of processors in a 4D Cartesian grid */
    cart4d.ndims = CART4D_NDIMS;
    cart4d.dims[0] = 0;
    cart4d.dims[1] = 0;
    cart4d.dims[2] = 0;
    cart4d.dims[3] = 1;
    MPI_Dims_create(world.size, cart4d.ndims, cart4d.dims);
    if (world.rank == world.root)
        printf("cart4d dims: <%d, %d, %d, %d>\n",
                cart4d.dims[0],
                cart4d.dims[1],
                cart4d.dims[2],
                cart4d.dims[3]
        );

    /* Create a new communicator with 4D Cartesian topology attached */
    cart4d.periods[0] = 0;
    cart4d.periods[1] = 0;
    cart4d.periods[2] = 0;
    cart4d.periods[3] = 0;
    MPI_Cart_create(world.comm, cart4d.ndims, cart4d.dims, cart4d.periods,
            1, &(cart4d.mpi_data.comm)
    );

    /* Fill-in 4D Cartesian communicator data */
    MPI_Comm_size(cart4d.mpi_data.comm, &(cart4d.mpi_data.size));
    MPI_Comm_rank(cart4d.mpi_data.comm, &(cart4d.mpi_data.rank));
    cart4d.mpi_data.root = 0;
    MPI_Cart_coords(cart4d.mpi_data.comm, cart4d.mpi_data.rank,
            cart4d.ndims, cart4d.coords
    );

    /* Create 2D subcommunicators and fill-in associated data */
    remain_dims[0] = 1;
    remain_dims[1] = 1;
    remain_dims[2] = 0;
    remain_dims[3] = 0;
    Create_2D_Subcomms(&cart4d, remain_dims, &cart2d_01);

    remain_dims[0] = 0;
    remain_dims[1] = 1;
    remain_dims[2] = 1;
    remain_dims[3] = 0;
    Create_2D_Subcomms(&cart4d, remain_dims, &cart2d_12);

    /* Print info on communicators */
    printf("world: %d; cart4d: %d, (%d, %d, %d, %d); "
            "cart2d_01: %d, (%d, %d); cart2d_12: %d, (%d, %d)\n",
            world.rank,
            cart4d.mpi_data.rank,
            cart4d.coords[0],
            cart4d.coords[1],
            cart4d.coords[2],
            cart4d.coords[3],
            cart2d_01.mpi_data.rank,
            cart2d_01.coords[0],
            cart2d_01.coords[1],
            cart2d_12.mpi_data.rank,
            cart2d_12.coords[0],
            cart2d_12.coords[1]
    );

    /* End of the program */
    MPI_Finalize();

    return EXIT_SUCCESS;
}
/* ----------------------------------------------------------------------- */

No comments:

Post a Comment