Blame test/mpi/coll/scatterv.c

Packit 0848f5
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit 0848f5
/*
Packit 0848f5
 *  (C) 2001 by Argonne National Laboratory.
Packit 0848f5
 *      See COPYRIGHT in top-level directory.
Packit 0848f5
 */
Packit 0848f5
#include "mpi.h"
Packit 0848f5
#include <stdlib.h>
Packit 0848f5
#include <stdio.h>
Packit 0848f5
Packit 0848f5
/* Prototypes for picky compilers */
Packit 0848f5
void SetData(double *, double *, int, int, int, int, int, int);
Packit 0848f5
int CheckData(double *, int, int, int, int, int, int);
Packit 0848f5
/*
Packit 0848f5
   This is an example of using scatterv to send a matrix from one
Packit 0848f5
   process to all others, with the matrix stored in Fortran order.
Packit 0848f5
   Note the use of an explicit UB to enable the sources to overlap.
Packit 0848f5
Packit 0848f5
   This tests scatterv to make sure that it uses the datatype size
Packit 0848f5
   and extent correctly.  It requires number of processors that
Packit 0848f5
   can be split with MPI_Dims_create.
Packit 0848f5
Packit 0848f5
 */
Packit 0848f5
Packit 0848f5
void SetData(double *sendbuf, double *recvbuf, int nx, int ny,
Packit 0848f5
             int myrow, int mycol, int nrow, int ncol)
Packit 0848f5
{
Packit 0848f5
    int coldim, i, j, m, k;
Packit 0848f5
    double *p;
Packit 0848f5
Packit 0848f5
    if (myrow == 0 && mycol == 0) {
Packit 0848f5
        coldim = nx * nrow;
Packit 0848f5
        for (j = 0; j < ncol; j++) {
Packit 0848f5
            for (i = 0; i < nrow; i++) {
Packit 0848f5
                p = sendbuf + i * nx + j * (ny * coldim);
Packit 0848f5
                for (m = 0; m < ny; m++) {
Packit 0848f5
                    for (k = 0; k < nx; k++) {
Packit 0848f5
                        p[k] = 1000 * j + 100 * i + m * nx + k;
Packit 0848f5
                    }
Packit 0848f5
                    p += coldim;
Packit 0848f5
                }
Packit 0848f5
            }
Packit 0848f5
        }
Packit 0848f5
    }
Packit 0848f5
    for (i = 0; i < nx * ny; i++)
Packit 0848f5
        recvbuf[i] = -1.0;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
int CheckData(double *recvbuf, int nx, int ny, int myrow, int mycol, int nrow, int expect_no_value)
Packit 0848f5
{
Packit 0848f5
    int coldim, m, k;
Packit 0848f5
    double *p, val;
Packit 0848f5
    int errs = 0;
Packit 0848f5
Packit 0848f5
    coldim = nx;
Packit 0848f5
    p = recvbuf;
Packit 0848f5
    for (m = 0; m < ny; m++) {
Packit 0848f5
        for (k = 0; k < nx; k++) {
Packit 0848f5
            /* If expect_no_value is true then we assume that the pre-scatterv
Packit 0848f5
             * value should remain in the recvbuf for our portion of the array.
Packit 0848f5
             * This is the case for the root process when using MPI_IN_PLACE. */
Packit 0848f5
            if (expect_no_value)
Packit 0848f5
                val = -1.0;
Packit 0848f5
            else
Packit 0848f5
                val = 1000 * mycol + 100 * myrow + m * nx + k;
Packit 0848f5
Packit 0848f5
            if (p[k] != val) {
Packit 0848f5
                errs++;
Packit 0848f5
                if (errs < 10) {
Packit 0848f5
                    printf("Error in (%d,%d) [%d,%d] location, got %f expected %f\n",
Packit 0848f5
                           m, k, myrow, mycol, p[k], val);
Packit 0848f5
                }
Packit 0848f5
                else if (errs == 10) {
Packit 0848f5
                    printf("Too many errors; suppressing printing\n");
Packit 0848f5
                }
Packit 0848f5
            }
Packit 0848f5
        }
Packit 0848f5
        p += coldim;
Packit 0848f5
    }
Packit 0848f5
    return errs;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
int main(int argc, char **argv)
Packit 0848f5
{
Packit 0848f5
    int rank, size, myrow, mycol, nx, ny, stride, cnt, i, j, errs, errs_in_place, tot_errs;
Packit 0848f5
    double *sendbuf, *recvbuf;
Packit 0848f5
    MPI_Datatype vec, block, types[2];
Packit 0848f5
    MPI_Aint displs[2];
Packit 0848f5
    int *scdispls;
Packit 0848f5
    int blens[2];
Packit 0848f5
    MPI_Comm comm2d;
Packit 0848f5
    int dims[2], periods[2], coords[2], lcoords[2];
Packit 0848f5
    int *sendcounts;
Packit 0848f5
Packit 0848f5
Packit 0848f5
    MPI_Init(&argc, &argv);
Packit 0848f5
    MPI_Comm_rank(MPI_COMM_WORLD, &rank;;
Packit 0848f5
    MPI_Comm_size(MPI_COMM_WORLD, &size);
Packit 0848f5
Packit 0848f5
    /* Get a 2-d decomposition of the processes */
Packit 0848f5
    dims[0] = 0;
Packit 0848f5
    dims[1] = 0;
Packit 0848f5
    MPI_Dims_create(size, 2, dims);
Packit 0848f5
    periods[0] = 0;
Packit 0848f5
    periods[1] = 0;
Packit 0848f5
    MPI_Cart_create(MPI_COMM_WORLD, 2, dims, periods, 0, &comm2d);
Packit 0848f5
    MPI_Cart_get(comm2d, 2, dims, periods, coords);
Packit 0848f5
    myrow = coords[0];
Packit 0848f5
    mycol = coords[1];
Packit 0848f5
/*
Packit 0848f5
    if (rank == 0)
Packit 0848f5
        printf("Decomposition is [%d x %d]\n", dims[0], dims[1]);
Packit 0848f5
*/
Packit 0848f5
Packit 0848f5
    /* Get the size of the matrix */
Packit 0848f5
    nx = 10;
Packit 0848f5
    ny = 8;
Packit 0848f5
    stride = nx * dims[0];
Packit 0848f5
Packit 0848f5
    recvbuf = (double *) malloc(nx * ny * sizeof(double));
Packit 0848f5
    if (!recvbuf) {
Packit 0848f5
        MPI_Abort(MPI_COMM_WORLD, 1);
Packit 0848f5
    }
Packit 0848f5
    sendbuf = 0;
Packit 0848f5
    if (myrow == 0 && mycol == 0) {
Packit 0848f5
        sendbuf = (double *) malloc(nx * ny * size * sizeof(double));
Packit 0848f5
        if (!sendbuf) {
Packit 0848f5
            MPI_Abort(MPI_COMM_WORLD, 1);
Packit 0848f5
        }
Packit 0848f5
    }
Packit 0848f5
    sendcounts = (int *) malloc(size * sizeof(int));
Packit 0848f5
    scdispls = (int *) malloc(size * sizeof(int));
Packit 0848f5
Packit 0848f5
    MPI_Type_vector(ny, nx, stride, MPI_DOUBLE, &vec;;
Packit 0848f5
    blens[0] = 1;
Packit 0848f5
    blens[1] = 1;
Packit 0848f5
    types[0] = vec;
Packit 0848f5
    types[1] = MPI_UB;
Packit 0848f5
    displs[0] = 0;
Packit 0848f5
    displs[1] = nx * sizeof(double);
Packit 0848f5
Packit 0848f5
    MPI_Type_struct(2, blens, displs, types, &block);
Packit 0848f5
    MPI_Type_free(&vec;;
Packit 0848f5
    MPI_Type_commit(&block);
Packit 0848f5
Packit 0848f5
    /* Set up the transfer */
Packit 0848f5
    cnt = 0;
Packit 0848f5
    for (i = 0; i < dims[1]; i++) {
Packit 0848f5
        for (j = 0; j < dims[0]; j++) {
Packit 0848f5
            sendcounts[cnt] = 1;
Packit 0848f5
            /* Using Cart_coords makes sure that ranks (used by
Packit 0848f5
             * sendrecv) matches the cartesian coordinates (used to
Packit 0848f5
             * set data in the matrix) */
Packit 0848f5
            MPI_Cart_coords(comm2d, cnt, 2, lcoords);
Packit 0848f5
            scdispls[cnt++] = lcoords[0] + lcoords[1] * (dims[0] * ny);
Packit 0848f5
        }
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    SetData(sendbuf, recvbuf, nx, ny, myrow, mycol, dims[0], dims[1]);
Packit 0848f5
    MPI_Scatterv(sendbuf, sendcounts, scdispls, block, recvbuf, nx * ny, MPI_DOUBLE, 0, comm2d);
Packit 0848f5
    if ((errs = CheckData(recvbuf, nx, ny, myrow, mycol, dims[0], 0))) {
Packit 0848f5
        fprintf(stdout, "Failed to transfer data\n");
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    /* once more, but this time passing MPI_IN_PLACE for the root */
Packit 0848f5
    SetData(sendbuf, recvbuf, nx, ny, myrow, mycol, dims[0], dims[1]);
Packit 0848f5
    MPI_Scatterv(sendbuf, sendcounts, scdispls, block,
Packit 0848f5
                 (rank == 0 ? MPI_IN_PLACE : recvbuf), nx * ny, MPI_DOUBLE, 0, comm2d);
Packit 0848f5
    errs_in_place = CheckData(recvbuf, nx, ny, myrow, mycol, dims[0], (rank == 0));
Packit 0848f5
    if (errs_in_place) {
Packit 0848f5
        fprintf(stdout, "Failed to transfer data (MPI_IN_PLACE)\n");
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    errs += errs_in_place;
Packit 0848f5
    MPI_Allreduce(&errs, &tot_errs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
Packit 0848f5
    if (rank == 0) {
Packit 0848f5
        if (tot_errs == 0)
Packit 0848f5
            printf(" No Errors\n");
Packit 0848f5
        else
Packit 0848f5
            printf("%d errors in use of MPI_SCATTERV\n", tot_errs);
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    if (sendbuf)
Packit 0848f5
        free(sendbuf);
Packit 0848f5
    free(recvbuf);
Packit 0848f5
    free(sendcounts);
Packit 0848f5
    free(scdispls);
Packit 0848f5
    MPI_Type_free(&block);
Packit 0848f5
    MPI_Comm_free(&comm2d);
Packit 0848f5
    MPI_Finalize();
Packit 0848f5
    return errs;
Packit 0848f5
}