|
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 |
}
|