1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
3 * (C) 2001 by Argonne National Laboratory.
4 * See COPYRIGHT in top-level directory.
10 /* Prototypes for picky compilers */
11 void SetData ( double *, double *, int, int, int, int, int, int );
12 int CheckData ( double *, int, int, int, int, int, int );
14 This is an example of using scatterv to send a matrix from one
15 process to all others, with the matrix stored in Fortran order.
16 Note the use of an explicit UB to enable the sources to overlap.
18 This tests scatterv to make sure that it uses the datatype size
19 and extent correctly. It requires number of processors that
20 can be split with MPI_Dims_create.
24 void SetData( double *sendbuf, double *recvbuf, int nx, int ny,
25 int myrow, int mycol, int nrow, int ncol )
27 int coldim, i, j, m, k;
30 if (myrow == 0 && mycol == 0) {
32 for (j=0; j<ncol; j++) {
33 for (i=0; i<nrow; i++) {
34 p = sendbuf + i * nx + j * (ny * coldim);
35 for (m=0; m<ny; m++) {
36 for (k=0; k<nx; k++) {
37 p[k] = 1000 * j + 100 * i + m * nx + k;
44 for (i=0; i<nx*ny; i++)
48 int CheckData( double *recvbuf,
49 int nx, int ny, int myrow, int mycol, int nrow,
58 for (m=0; m<ny; m++) {
59 for (k=0; k<nx; k++) {
60 /* If expect_no_value is true then we assume that the pre-scatterv
61 * value should remain in the recvbuf for our portion of the array.
62 * This is the case for the root process when using MPI_IN_PLACE. */
66 val = 1000 * mycol + 100 * myrow + m * nx + k;
71 printf("Error in (%d,%d) [%d,%d] location, got %f expected %f\n",
72 m, k, myrow, mycol, p[k], val );
74 else if (errs == 10) {
75 printf( "Too many errors; suppressing printing\n" );
84 int main( int argc, char **argv )
86 int rank, size, myrow, mycol, nx, ny, stride, cnt, i, j, errs, errs_in_place, tot_errs;
87 double *sendbuf, *recvbuf;
88 MPI_Datatype vec, block, types[2];
93 int dims[2], periods[2], coords[2], lcoords[2];
97 MPI_Init( &argc, &argv );
98 MPI_Comm_rank( MPI_COMM_WORLD, &rank );
99 MPI_Comm_size( MPI_COMM_WORLD, &size );
101 /* Get a 2-d decomposition of the processes */
102 dims[0] = 0; dims[1] = 0;
103 MPI_Dims_create( size, 2, dims );
104 periods[0] = 0; periods[1] = 0;
105 MPI_Cart_create( MPI_COMM_WORLD, 2, dims, periods, 0, &comm2d );
106 MPI_Cart_get( comm2d, 2, dims, periods, coords );
111 printf( "Decomposition is [%d x %d]\n", dims[0], dims[1] );
114 /* Get the size of the matrix */
117 stride = nx * dims[0];
119 recvbuf = (double *)malloc( nx * ny * sizeof(double) );
121 MPI_Abort( MPI_COMM_WORLD, 1 );
124 if (myrow == 0 && mycol == 0) {
125 sendbuf = (double *)malloc( nx * ny * size * sizeof(double) );
127 MPI_Abort( MPI_COMM_WORLD, 1 );
130 sendcounts = (int *) malloc( size * sizeof(int) );
131 scdispls = (int *)malloc( size * sizeof(int) );
133 MPI_Type_vector( ny, nx, stride, MPI_DOUBLE, &vec );
134 blens[0] = 1; blens[1] = 1;
135 types[0] = vec; types[1] = MPI_UB;
136 displs[0] = 0; displs[1] = nx * sizeof(double);
138 MPI_Type_struct( 2, blens, displs, types, &block );
139 MPI_Type_free( &vec );
140 MPI_Type_commit( &block );
142 /* Set up the transfer */
144 for (i=0; i<dims[1]; i++) {
145 for (j=0; j<dims[0]; j++) {
147 /* Using Cart_coords makes sure that ranks (used by
148 sendrecv) matches the cartesian coordinates (used to
149 set data in the matrix) */
150 MPI_Cart_coords( comm2d, cnt, 2, lcoords );
151 scdispls[cnt++] = lcoords[0] + lcoords[1] * (dims[0] * ny);
155 SetData( sendbuf, recvbuf, nx, ny, myrow, mycol, dims[0], dims[1] );
156 MPI_Scatterv( sendbuf, sendcounts, scdispls, block,
157 recvbuf, nx * ny, MPI_DOUBLE, 0, comm2d );
158 if((errs = CheckData( recvbuf, nx, ny, myrow, mycol, dims[0], 0 ))) {
159 fprintf( stdout, "Failed to transfer data\n" );
162 /* once more, but this time passing MPI_IN_PLACE for the root */
163 SetData( sendbuf, recvbuf, nx, ny, myrow, mycol, dims[0], dims[1] );
164 MPI_Scatterv( sendbuf, sendcounts, scdispls, block,
165 (rank == 0 ? MPI_IN_PLACE : recvbuf), nx * ny, MPI_DOUBLE, 0, comm2d );
166 errs_in_place = CheckData( recvbuf, nx, ny, myrow, mycol, dims[0], (rank == 0) );
168 fprintf( stdout, "Failed to transfer data (MPI_IN_PLACE)\n" );
171 errs += errs_in_place;
172 MPI_Allreduce( &errs, &tot_errs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD );
175 printf( " No Errors\n" );
177 printf( "%d errors in use of MPI_SCATTERV\n", tot_errs );
180 if (sendbuf) free( sendbuf );
184 MPI_Type_free( &block );
185 MPI_Comm_free( &comm2d );