1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
3 * (C) 2011 by Argonne National Laboratory.
4 * See COPYRIGHT in top-level directory.
7 /* A basic test of all 17 nonblocking collective operations specified by the
8 * draft MPI-3 standard. It only exercises the intracommunicator functionality,
9 * does not use MPI_IN_PLACE, and only transmits/receives simple integer types
10 * with relatively small counts. It does check a few fancier issues, such as
11 * ensuring that "premature user releases" of MPI_Op and MPI_Datatype objects
12 * does not result in an error or segfault. */
17 /* USE_STRICT_MPI may be defined in mpitestconf.h */
18 #include "mpitestconf.h"
23 #define my_assert(cond_) \
26 fprintf(stderr, "assertion (%s) failed, aborting\n", #cond_); \
27 MPI_Abort(MPI_COMM_WORLD, 1); \
31 /* Since MPICH is currently the only NBC implementation in existence, just use
32 * this quick-and-dirty #ifdef to decide whether to test the nonblocking
33 * collectives. Eventually we can add a configure option or configure test, or
34 * the MPI-3 standard will be released and these can be gated on a MPI_VERSION
36 #if !defined(USE_STRICT_MPI) && defined(MPICH)
37 #define TEST_NBC_ROUTINES 1
40 static void sum_fn(void *invec, void *inoutvec, int *len, MPI_Datatype *datatype)
44 int *inout = inoutvec;
45 for (i = 0; i < *len; ++i) {
46 inout[i] = in[i] + inout[i];
51 int main(int argc, char **argv)
57 int *sendcounts = NULL;
58 int *recvcounts = NULL;
61 int *sendtypes = NULL;
62 int *recvtypes = NULL;
63 char *buf_alias = NULL;
66 MPI_Init(&argc, &argv);
67 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
68 MPI_Comm_size(MPI_COMM_WORLD, &size);
69 #if defined(TEST_NBC_ROUTINES)
71 buf = malloc(COUNT*size*sizeof(int));
72 recvbuf = malloc(COUNT*size*sizeof(int));
73 sendcounts = malloc(size*sizeof(int));
74 recvcounts = malloc(size*sizeof(int));
75 sdispls = malloc(size*sizeof(int));
76 rdispls = malloc(size*sizeof(int));
77 sendtypes = malloc(size*sizeof(MPI_Datatype));
78 recvtypes = malloc(size*sizeof(MPI_Datatype));
81 for (i = 0; i < COUNT; ++i) {
89 MPI_Ibcast(buf, COUNT, MPI_INT, 0, MPI_COMM_WORLD, &req);
90 MPI_Wait(&req, MPI_STATUS_IGNORE);
92 for (i = 0; i < COUNT; ++i) {
94 printf("buf[%d]=%d i=%d\n", i, buf[i], i);
95 my_assert(buf[i] == i);
98 /* MPI_Ibcast (again, but designed to stress scatter/allgather impls) */
99 buf_alias = (char *)buf;
100 my_assert(COUNT*size*sizeof(int) > PRIME); /* sanity */
101 for (i = 0; i < PRIME; ++i) {
107 for (i = PRIME; i < COUNT * size * sizeof(int); ++i) {
110 MPI_Ibcast(buf, PRIME, MPI_SIGNED_CHAR, 0, MPI_COMM_WORLD, &req);
111 MPI_Wait(&req, MPI_STATUS_IGNORE);
112 for (i = 0; i < PRIME; ++i) {
113 if (buf_alias[i] != i)
114 printf("buf_alias[%d]=%d i=%d\n", i, buf_alias[i], i);
115 my_assert(buf_alias[i] == i);
119 MPI_Ibarrier(MPI_COMM_WORLD, &req);
120 MPI_Wait(&req, MPI_STATUS_IGNORE);
123 for (i = 0; i < COUNT; ++i) {
125 recvbuf[i] = 0xdeadbeef;
127 MPI_Ireduce(buf, recvbuf, COUNT, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD, &req);
128 MPI_Wait(&req, MPI_STATUS_IGNORE);
130 for (i = 0; i < COUNT; ++i) {
131 if (recvbuf[i] != ((size * (size-1) / 2) + (i * size)))
132 printf("got recvbuf[%d]=%d, expected %d\n", i, recvbuf[i], ((size * (size-1) / 2) + (i * size)));
133 my_assert(recvbuf[i] == ((size * (size-1) / 2) + (i * size)));
137 /* same again, use a user op and free it before the wait */
139 MPI_Op op = MPI_OP_NULL;
140 MPI_Op_create(sum_fn, /*commute=*/1, &op);
142 for (i = 0; i < COUNT; ++i) {
144 recvbuf[i] = 0xdeadbeef;
146 MPI_Ireduce(buf, recvbuf, COUNT, MPI_INT, op, 0, MPI_COMM_WORLD, &req);
148 MPI_Wait(&req, MPI_STATUS_IGNORE);
150 for (i = 0; i < COUNT; ++i) {
151 if (recvbuf[i] != ((size * (size-1) / 2) + (i * size)))
152 printf("got recvbuf[%d]=%d, expected %d\n", i, recvbuf[i], ((size * (size-1) / 2) + (i * size)));
153 my_assert(recvbuf[i] == ((size * (size-1) / 2) + (i * size)));
159 for (i = 0; i < COUNT; ++i) {
161 recvbuf[i] = 0xdeadbeef;
163 MPI_Iallreduce(buf, recvbuf, COUNT, MPI_INT, MPI_SUM, MPI_COMM_WORLD, &req);
164 MPI_Wait(&req, MPI_STATUS_IGNORE);
165 for (i = 0; i < COUNT; ++i) {
166 if (recvbuf[i] != ((size * (size-1) / 2) + (i * size)))
167 printf("got recvbuf[%d]=%d, expected %d\n", i, recvbuf[i], ((size * (size-1) / 2) + (i * size)));
168 my_assert(recvbuf[i] == ((size * (size-1) / 2) + (i * size)));
171 /* MPI_Ialltoallv (a weak test, neither irregular nor sparse) */
172 for (i = 0; i < size; ++i) {
173 sendcounts[i] = COUNT;
174 recvcounts[i] = COUNT;
175 sdispls[i] = COUNT * i;
176 rdispls[i] = COUNT * i;
177 for (j = 0; j < COUNT; ++j) {
178 buf[i*COUNT+j] = rank + (i * j);
179 recvbuf[i*COUNT+j] = 0xdeadbeef;
182 MPI_Ialltoallv(buf, sendcounts, sdispls, MPI_INT, recvbuf, recvcounts, rdispls, MPI_INT, MPI_COMM_WORLD, &req);
183 MPI_Wait(&req, MPI_STATUS_IGNORE);
184 for (i = 0; i < size; ++i) {
185 for (j = 0; j < COUNT; ++j) {
186 /*printf("recvbuf[%d*COUNT+%d]=%d, expecting %d\n", i, j, recvbuf[i*COUNT+j], (i + (rank * j)));*/
187 my_assert(recvbuf[i*COUNT+j] == (i + (rank * j)));
192 for (i = 0; i < size*COUNT; ++i) {
194 recvbuf[i] = 0xdeadbeef;
196 MPI_Igather(buf, COUNT, MPI_INT, recvbuf, COUNT, MPI_INT, 0, MPI_COMM_WORLD, &req);
197 MPI_Wait(&req, MPI_STATUS_IGNORE);
199 for (i = 0; i < size; ++i) {
200 for (j = 0; j < COUNT; ++j) {
201 my_assert(recvbuf[i*COUNT+j] == i + j);
206 for (i = 0; i < size*COUNT; ++i) {
207 my_assert(recvbuf[i] == 0xdeadbeef);
211 /* same test again, just use a dup'ed datatype and free it before the wait */
213 MPI_Datatype type = MPI_DATATYPE_NULL;
214 MPI_Type_dup(MPI_INT, &type);
216 for (i = 0; i < size*COUNT; ++i) {
218 recvbuf[i] = 0xdeadbeef;
220 MPI_Igather(buf, COUNT, MPI_INT, recvbuf, COUNT, type, 0, MPI_COMM_WORLD, &req);
221 MPI_Type_free(&type); /* should cause implementations that don't refcount
222 correctly to blow up or hang in the wait */
223 MPI_Wait(&req, MPI_STATUS_IGNORE);
225 for (i = 0; i < size; ++i) {
226 for (j = 0; j < COUNT; ++j) {
227 my_assert(recvbuf[i*COUNT+j] == i + j);
232 for (i = 0; i < size*COUNT; ++i) {
233 my_assert(recvbuf[i] == 0xdeadbeef);
239 for (i = 0; i < size; ++i) {
240 for (j = 0; j < COUNT; ++j) {
242 buf[i*COUNT+j] = i + j;
244 buf[i*COUNT+j] = 0xdeadbeef;
245 recvbuf[i*COUNT+j] = 0xdeadbeef;
248 MPI_Iscatter(buf, COUNT, MPI_INT, recvbuf, COUNT, MPI_INT, 0, MPI_COMM_WORLD, &req);
249 MPI_Wait(&req, MPI_STATUS_IGNORE);
250 for (j = 0; j < COUNT; ++j) {
251 my_assert(recvbuf[j] == rank + j);
254 for (i = 0; i < size*COUNT; ++i) {
255 /* check we didn't corrupt the sendbuf somehow */
256 my_assert(buf[i] == 0xdeadbeef);
261 for (i = 0; i < size; ++i) {
262 /* weak test, just test the regular case where all counts are equal */
263 sendcounts[i] = COUNT;
264 sdispls[i] = i * COUNT;
265 for (j = 0; j < COUNT; ++j) {
267 buf[i*COUNT+j] = i + j;
269 buf[i*COUNT+j] = 0xdeadbeef;
270 recvbuf[i*COUNT+j] = 0xdeadbeef;
273 MPI_Iscatterv(buf, sendcounts, sdispls, MPI_INT, recvbuf, COUNT, MPI_INT, 0, MPI_COMM_WORLD, &req);
274 MPI_Wait(&req, MPI_STATUS_IGNORE);
275 for (j = 0; j < COUNT; ++j) {
276 my_assert(recvbuf[j] == rank + j);
279 for (i = 0; i < size*COUNT; ++i) {
280 /* check we didn't corrupt the sendbuf somehow */
281 my_assert(buf[i] == 0xdeadbeef);
284 for (i = 1; i < size; ++i) {
285 for (j = 0; j < COUNT; ++j) {
286 /* check we didn't corrupt the rest of the recvbuf */
287 my_assert(recvbuf[i*COUNT+j] == 0xdeadbeef);
291 /* MPI_Ireduce_scatter */
292 for (i = 0; i < size; ++i) {
293 recvcounts[i] = COUNT;
294 for (j = 0; j < COUNT; ++j) {
295 buf[i*COUNT+j] = rank + i;
296 recvbuf[i*COUNT+j] = 0xdeadbeef;
299 MPI_Ireduce_scatter(buf, recvbuf, recvcounts, MPI_INT, MPI_SUM, MPI_COMM_WORLD, &req);
300 MPI_Wait(&req, MPI_STATUS_IGNORE);
301 for (j = 0; j < COUNT; ++j) {
302 my_assert(recvbuf[j] == (size * rank + ((size - 1) * size) / 2));
304 for (i = 1; i < size; ++i) {
305 for (j = 0; j < COUNT; ++j) {
306 /* check we didn't corrupt the rest of the recvbuf */
307 my_assert(recvbuf[i*COUNT+j] == 0xdeadbeef);
311 /* MPI_Ireduce_scatter_block */
312 for (i = 0; i < size; ++i) {
313 for (j = 0; j < COUNT; ++j) {
314 buf[i*COUNT+j] = rank + i;
315 recvbuf[i*COUNT+j] = 0xdeadbeef;
318 MPI_Ireduce_scatter_block(buf, recvbuf, COUNT, MPI_INT, MPI_SUM, MPI_COMM_WORLD, &req);
319 MPI_Wait(&req, MPI_STATUS_IGNORE);
320 for (j = 0; j < COUNT; ++j) {
321 my_assert(recvbuf[j] == (size * rank + ((size - 1) * size) / 2));
323 for (i = 1; i < size; ++i) {
324 for (j = 0; j < COUNT; ++j) {
325 /* check we didn't corrupt the rest of the recvbuf */
326 my_assert(recvbuf[i*COUNT+j] == 0xdeadbeef);
331 for (i = 0; i < size*COUNT; ++i) {
333 recvbuf[i] = 0xdeadbeef;
335 for (i = 0; i < COUNT; ++i) {
338 for (i = 0; i < size; ++i) {
339 recvcounts[i] = COUNT;
340 rdispls[i] = i * COUNT;
342 MPI_Igatherv(buf, COUNT, MPI_INT, recvbuf, recvcounts, rdispls, MPI_INT, 0, MPI_COMM_WORLD, &req);
343 MPI_Wait(&req, MPI_STATUS_IGNORE);
345 for (i = 0; i < size; ++i) {
346 for (j = 0; j < COUNT; ++j) {
347 my_assert(recvbuf[i*COUNT+j] == i + j);
352 for (i = 0; i < size*COUNT; ++i) {
353 my_assert(recvbuf[i] == 0xdeadbeef);
358 for (i = 0; i < size; ++i) {
359 for (j = 0; j < COUNT; ++j) {
360 buf[i*COUNT+j] = rank + (i * j);
361 recvbuf[i*COUNT+j] = 0xdeadbeef;
364 MPI_Ialltoall(buf, COUNT, MPI_INT, recvbuf, COUNT, MPI_INT, MPI_COMM_WORLD, &req);
365 MPI_Wait(&req, MPI_STATUS_IGNORE);
366 for (i = 0; i < size; ++i) {
367 for (j = 0; j < COUNT; ++j) {
368 /*printf("recvbuf[%d*COUNT+%d]=%d, expecting %d\n", i, j, recvbuf[i*COUNT+j], (i + (i * j)));*/
369 my_assert(recvbuf[i*COUNT+j] == (i + (rank * j)));
374 for (i = 0; i < size*COUNT; ++i) {
376 recvbuf[i] = 0xdeadbeef;
378 MPI_Iallgather(buf, COUNT, MPI_INT, recvbuf, COUNT, MPI_INT, MPI_COMM_WORLD, &req);
379 MPI_Wait(&req, MPI_STATUS_IGNORE);
380 for (i = 0; i < size; ++i) {
381 for (j = 0; j < COUNT; ++j) {
382 my_assert(recvbuf[i*COUNT+j] == i + j);
386 /* MPI_Iallgatherv */
387 for (i = 0; i < size; ++i) {
388 for (j = 0; j < COUNT; ++j) {
389 recvbuf[i*COUNT+j] = 0xdeadbeef;
391 recvcounts[i] = COUNT;
392 rdispls[i] = i * COUNT;
394 for (i = 0; i < COUNT; ++i)
396 MPI_Iallgatherv(buf, COUNT, MPI_INT, recvbuf, recvcounts, rdispls, MPI_INT, MPI_COMM_WORLD, &req);
397 MPI_Wait(&req, MPI_STATUS_IGNORE);
398 for (i = 0; i < size; ++i) {
399 for (j = 0; j < COUNT; ++j) {
400 my_assert(recvbuf[i*COUNT+j] == i + j);
405 for (i = 0; i < COUNT; ++i) {
407 recvbuf[i] = 0xdeadbeef;
409 MPI_Iscan(buf, recvbuf, COUNT, MPI_INT, MPI_SUM, MPI_COMM_WORLD, &req);
410 MPI_Wait(&req, MPI_STATUS_IGNORE);
411 for (i = 0; i < COUNT; ++i) {
412 my_assert(recvbuf[i] == ((rank * (rank+1) / 2) + (i * (rank + 1))));
416 for (i = 0; i < COUNT; ++i) {
418 recvbuf[i] = 0xdeadbeef;
420 MPI_Iexscan(buf, recvbuf, COUNT, MPI_INT, MPI_SUM, MPI_COMM_WORLD, &req);
421 MPI_Wait(&req, MPI_STATUS_IGNORE);
422 for (i = 0; i < COUNT; ++i) {
424 my_assert(recvbuf[i] == 0xdeadbeef);
426 my_assert(recvbuf[i] == ((rank * (rank+1) / 2) + (i * (rank + 1)) - (rank + i)));
429 /* MPI_Ialltoallw (a weak test, neither irregular nor sparse) */
430 for (i = 0; i < size; ++i) {
431 sendcounts[i] = COUNT;
432 recvcounts[i] = COUNT;
433 sdispls[i] = COUNT * i * sizeof(int);
434 rdispls[i] = COUNT * i * sizeof(int);
435 sendtypes[i] = MPI_INT;
436 recvtypes[i] = MPI_INT;
437 for (j = 0; j < COUNT; ++j) {
438 buf[i*COUNT+j] = rank + (i * j);
439 recvbuf[i*COUNT+j] = 0xdeadbeef;
442 MPI_Ialltoallw(buf, sendcounts, sdispls, sendtypes, recvbuf, recvcounts, rdispls, recvtypes, MPI_COMM_WORLD, &req);
443 MPI_Wait(&req, MPI_STATUS_IGNORE);
444 for (i = 0; i < size; ++i) {
445 for (j = 0; j < COUNT; ++j) {
446 /*printf("recvbuf[%d*COUNT+%d]=%d, expecting %d\n", i, j, recvbuf[i*COUNT+j], (i + (rank * j)));*/
447 my_assert(recvbuf[i*COUNT+j] == (i + (rank * j)));
451 #endif /* defined(TEST_NBC_ROUTINES) */
454 printf(" No Errors\n");