1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
3 * (C) 2012 by Argonne National Laboratory.
4 * See COPYRIGHT in top-level directory.
13 /* assert-like macro that bumps the err count and emits a message */
19 fprintf(stderr, "check failed: (%s), line %d\n", #x_, __LINE__); \
25 #define LARGE_SZ (LARGE_DIM * LARGE_DIM)
27 int main(int argc, char **argv)
32 int *sendbuf = NULL, *recvbuf = NULL;
39 MPI_Init(&argc, &argv);
41 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
42 MPI_Comm_size(MPI_COMM_WORLD, &size);
45 printf("this test requires at least 2 processes\n");
46 MPI_Abort(MPI_COMM_WORLD, 1);
49 /* all processes besides ranks 0 & 1 aren't used by this test */
54 sendbuf = (int *) malloc(LARGE_SZ * sizeof(int));
55 recvbuf = (int *) malloc(LARGE_SZ * sizeof(int));
56 if (sendbuf == NULL || recvbuf == NULL) {
57 printf("Error in memory allocation\n");
58 MPI_Abort(MPI_COMM_WORLD, 1);
61 /* test 0: simple send & mprobe+mrecv */
63 sendbuf[0] = 0xdeadbeef;
64 sendbuf[1] = 0xfeedface;
65 MPI_Send(sendbuf, 2, MPI_INT, 1, 5, MPI_COMM_WORLD);
68 memset(&s1, 0xab, sizeof(MPI_Status));
69 memset(&s2, 0xab, sizeof(MPI_Status));
70 /* the error field should remain unmodified */
71 s1.MPI_ERROR = MPI_ERR_DIMS;
72 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
74 msg = MPI_MESSAGE_NULL;
75 MPI_Mprobe(0, 5, MPI_COMM_WORLD, &msg, &s1);
76 check(s1.MPI_SOURCE == 0);
77 check(s1.MPI_TAG == 5);
78 check(s1.MPI_ERROR == MPI_ERR_DIMS);
79 check(msg != MPI_MESSAGE_NULL);
82 MPI_Get_count(&s1, MPI_INT, &count);
85 recvbuf[0] = 0x01234567;
86 recvbuf[1] = 0x89abcdef;
87 MPI_Mrecv(recvbuf, count, MPI_INT, &msg, &s2);
88 check(recvbuf[0] == 0xdeadbeef);
89 check(recvbuf[1] == 0xfeedface);
90 check(s2.MPI_SOURCE == 0);
91 check(s2.MPI_TAG == 5);
92 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
93 check(msg == MPI_MESSAGE_NULL);
96 /* test 1: simple send & mprobe+imrecv */
98 sendbuf[0] = 0xdeadbeef;
99 sendbuf[1] = 0xfeedface;
100 MPI_Send(sendbuf, 2, MPI_INT, 1, 5, MPI_COMM_WORLD);
103 memset(&s1, 0xab, sizeof(MPI_Status));
104 memset(&s2, 0xab, sizeof(MPI_Status));
105 /* the error field should remain unmodified */
106 s1.MPI_ERROR = MPI_ERR_DIMS;
107 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
109 msg = MPI_MESSAGE_NULL;
110 MPI_Mprobe(0, 5, MPI_COMM_WORLD, &msg, &s1);
111 check(s1.MPI_SOURCE == 0);
112 check(s1.MPI_TAG == 5);
113 check(s1.MPI_ERROR == MPI_ERR_DIMS);
114 check(msg != MPI_MESSAGE_NULL);
117 MPI_Get_count(&s1, MPI_INT, &count);
120 rreq = MPI_REQUEST_NULL;
121 recvbuf[0] = 0x01234567;
122 recvbuf[1] = 0x89abcdef;
123 MPI_Imrecv(recvbuf, count, MPI_INT, &msg, &rreq);
124 check(rreq != MPI_REQUEST_NULL);
125 MPI_Wait(&rreq, &s2);
126 check(recvbuf[0] == 0xdeadbeef);
127 check(recvbuf[1] == 0xfeedface);
128 check(s2.MPI_SOURCE == 0);
129 check(s2.MPI_TAG == 5);
130 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
131 check(msg == MPI_MESSAGE_NULL);
134 /* test 2: simple send & improbe+mrecv */
136 sendbuf[0] = 0xdeadbeef;
137 sendbuf[1] = 0xfeedface;
138 MPI_Send(sendbuf, 2, MPI_INT, 1, 5, MPI_COMM_WORLD);
141 memset(&s1, 0xab, sizeof(MPI_Status));
142 memset(&s2, 0xab, sizeof(MPI_Status));
143 /* the error field should remain unmodified */
144 s1.MPI_ERROR = MPI_ERR_DIMS;
145 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
147 msg = MPI_MESSAGE_NULL;
149 check(msg == MPI_MESSAGE_NULL);
150 MPI_Improbe(0, 5, MPI_COMM_WORLD, &found, &msg, &s1);
152 check(msg != MPI_MESSAGE_NULL);
153 check(s1.MPI_SOURCE == 0);
154 check(s1.MPI_TAG == 5);
155 check(s1.MPI_ERROR == MPI_ERR_DIMS);
158 MPI_Get_count(&s1, MPI_INT, &count);
161 recvbuf[0] = 0x01234567;
162 recvbuf[1] = 0x89abcdef;
163 MPI_Mrecv(recvbuf, count, MPI_INT, &msg, &s2);
164 check(recvbuf[0] == 0xdeadbeef);
165 check(recvbuf[1] == 0xfeedface);
166 check(s2.MPI_SOURCE == 0);
167 check(s2.MPI_TAG == 5);
168 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
169 check(msg == MPI_MESSAGE_NULL);
172 /* test 3: simple send & improbe+imrecv */
174 sendbuf[0] = 0xdeadbeef;
175 sendbuf[1] = 0xfeedface;
176 MPI_Send(sendbuf, 2, MPI_INT, 1, 5, MPI_COMM_WORLD);
179 memset(&s1, 0xab, sizeof(MPI_Status));
180 memset(&s2, 0xab, sizeof(MPI_Status));
181 /* the error field should remain unmodified */
182 s1.MPI_ERROR = MPI_ERR_DIMS;
183 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
185 msg = MPI_MESSAGE_NULL;
187 check(msg == MPI_MESSAGE_NULL);
188 MPI_Improbe(0, 5, MPI_COMM_WORLD, &found, &msg, &s1);
190 check(msg != MPI_MESSAGE_NULL);
191 check(s1.MPI_SOURCE == 0);
192 check(s1.MPI_TAG == 5);
193 check(s1.MPI_ERROR == MPI_ERR_DIMS);
196 MPI_Get_count(&s1, MPI_INT, &count);
199 rreq = MPI_REQUEST_NULL;
200 MPI_Imrecv(recvbuf, count, MPI_INT, &msg, &rreq);
201 check(rreq != MPI_REQUEST_NULL);
202 MPI_Wait(&rreq, &s2);
203 check(recvbuf[0] == 0xdeadbeef);
204 check(recvbuf[1] == 0xfeedface);
205 check(s2.MPI_SOURCE == 0);
206 check(s2.MPI_TAG == 5);
207 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
208 check(msg == MPI_MESSAGE_NULL);
211 /* test 4: mprobe+mrecv with MPI_PROC_NULL */
213 memset(&s1, 0xab, sizeof(MPI_Status));
214 memset(&s2, 0xab, sizeof(MPI_Status));
215 /* the error field should remain unmodified */
216 s1.MPI_ERROR = MPI_ERR_DIMS;
217 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
219 msg = MPI_MESSAGE_NULL;
220 MPI_Mprobe(MPI_PROC_NULL, 5, MPI_COMM_WORLD, &msg, &s1);
221 check(s1.MPI_SOURCE == MPI_PROC_NULL);
222 check(s1.MPI_TAG == MPI_ANY_TAG);
223 check(s1.MPI_ERROR == MPI_ERR_DIMS);
224 check(msg == MPI_MESSAGE_NO_PROC);
227 MPI_Get_count(&s1, MPI_INT, &count);
230 recvbuf[0] = 0x01234567;
231 recvbuf[1] = 0x89abcdef;
232 MPI_Mrecv(recvbuf, count, MPI_INT, &msg, &s2);
233 /* recvbuf should remain unmodified */
234 check(recvbuf[0] == 0x01234567);
235 check(recvbuf[1] == 0x89abcdef);
236 /* should get back "proc null status" */
237 check(s2.MPI_SOURCE == MPI_PROC_NULL);
238 check(s2.MPI_TAG == MPI_ANY_TAG);
239 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
240 check(msg == MPI_MESSAGE_NULL);
242 MPI_Get_count(&s2, MPI_INT, &count);
246 /* test 5: mprobe+imrecv with MPI_PROC_NULL */
248 memset(&s1, 0xab, sizeof(MPI_Status));
249 memset(&s2, 0xab, sizeof(MPI_Status));
250 /* the error field should remain unmodified */
251 s1.MPI_ERROR = MPI_ERR_DIMS;
252 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
254 msg = MPI_MESSAGE_NULL;
255 MPI_Mprobe(MPI_PROC_NULL, 5, MPI_COMM_WORLD, &msg, &s1);
256 check(s1.MPI_SOURCE == MPI_PROC_NULL);
257 check(s1.MPI_TAG == MPI_ANY_TAG);
258 check(s1.MPI_ERROR == MPI_ERR_DIMS);
259 check(msg == MPI_MESSAGE_NO_PROC);
261 MPI_Get_count(&s1, MPI_INT, &count);
264 rreq = MPI_REQUEST_NULL;
265 recvbuf[0] = 0x01234567;
266 recvbuf[1] = 0x89abcdef;
267 MPI_Imrecv(recvbuf, count, MPI_INT, &msg, &rreq);
268 check(rreq != MPI_REQUEST_NULL);
270 MPI_Test(&rreq, &completed, &s2); /* single test should always succeed */
272 /* recvbuf should remain unmodified */
273 check(recvbuf[0] == 0x01234567);
274 check(recvbuf[1] == 0x89abcdef);
275 /* should get back "proc null status" */
276 check(s2.MPI_SOURCE == MPI_PROC_NULL);
277 check(s2.MPI_TAG == MPI_ANY_TAG);
278 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
279 check(msg == MPI_MESSAGE_NULL);
281 MPI_Get_count(&s2, MPI_INT, &count);
285 /* test 6: improbe+mrecv with MPI_PROC_NULL */
287 memset(&s1, 0xab, sizeof(MPI_Status));
288 memset(&s2, 0xab, sizeof(MPI_Status));
289 /* the error field should remain unmodified */
290 s1.MPI_ERROR = MPI_ERR_DIMS;
291 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
293 msg = MPI_MESSAGE_NULL;
295 MPI_Improbe(MPI_PROC_NULL, 5, MPI_COMM_WORLD, &found, &msg, &s1);
297 check(msg == MPI_MESSAGE_NO_PROC);
298 check(s1.MPI_SOURCE == MPI_PROC_NULL);
299 check(s1.MPI_TAG == MPI_ANY_TAG);
300 check(s1.MPI_ERROR == MPI_ERR_DIMS);
302 MPI_Get_count(&s1, MPI_INT, &count);
305 recvbuf[0] = 0x01234567;
306 recvbuf[1] = 0x89abcdef;
307 MPI_Mrecv(recvbuf, count, MPI_INT, &msg, &s2);
308 /* recvbuf should remain unmodified */
309 check(recvbuf[0] == 0x01234567);
310 check(recvbuf[1] == 0x89abcdef);
311 /* should get back "proc null status" */
312 check(s2.MPI_SOURCE == MPI_PROC_NULL);
313 check(s2.MPI_TAG == MPI_ANY_TAG);
314 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
315 check(msg == MPI_MESSAGE_NULL);
317 MPI_Get_count(&s2, MPI_INT, &count);
321 /* test 7: improbe+imrecv */
323 memset(&s1, 0xab, sizeof(MPI_Status));
324 memset(&s2, 0xab, sizeof(MPI_Status));
325 /* the error field should remain unmodified */
326 s1.MPI_ERROR = MPI_ERR_DIMS;
327 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
329 msg = MPI_MESSAGE_NULL;
330 MPI_Improbe(MPI_PROC_NULL, 5, MPI_COMM_WORLD, &found, &msg, &s1);
332 check(msg == MPI_MESSAGE_NO_PROC);
333 check(s1.MPI_SOURCE == MPI_PROC_NULL);
334 check(s1.MPI_TAG == MPI_ANY_TAG);
335 check(s1.MPI_ERROR == MPI_ERR_DIMS);
337 MPI_Get_count(&s1, MPI_INT, &count);
340 rreq = MPI_REQUEST_NULL;
341 MPI_Imrecv(recvbuf, count, MPI_INT, &msg, &rreq);
342 check(rreq != MPI_REQUEST_NULL);
344 MPI_Test(&rreq, &completed, &s2); /* single test should always succeed */
346 /* recvbuf should remain unmodified */
347 check(recvbuf[0] == 0x01234567);
348 check(recvbuf[1] == 0x89abcdef);
349 /* should get back "proc null status" */
350 check(s2.MPI_SOURCE == MPI_PROC_NULL);
351 check(s2.MPI_TAG == MPI_ANY_TAG);
352 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
353 check(msg == MPI_MESSAGE_NULL);
355 MPI_Get_count(&s2, MPI_INT, &count);
359 /* test 8: simple ssend & mprobe+mrecv */
361 sendbuf[0] = 0xdeadbeef;
362 sendbuf[1] = 0xfeedface;
363 MPI_Ssend(sendbuf, 2, MPI_INT, 1, 5, MPI_COMM_WORLD);
366 memset(&s1, 0xab, sizeof(MPI_Status));
367 memset(&s2, 0xab, sizeof(MPI_Status));
368 /* the error field should remain unmodified */
369 s1.MPI_ERROR = MPI_ERR_DIMS;
370 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
372 msg = MPI_MESSAGE_NULL;
373 MPI_Mprobe(0, 5, MPI_COMM_WORLD, &msg, &s1);
374 check(s1.MPI_SOURCE == 0);
375 check(s1.MPI_TAG == 5);
376 check(s1.MPI_ERROR == MPI_ERR_DIMS);
377 check(msg != MPI_MESSAGE_NULL);
380 MPI_Get_count(&s1, MPI_INT, &count);
383 recvbuf[0] = 0x01234567;
384 recvbuf[1] = 0x89abcdef;
385 MPI_Mrecv(recvbuf, count, MPI_INT, &msg, &s2);
386 check(recvbuf[0] == 0xdeadbeef);
387 check(recvbuf[1] == 0xfeedface);
388 check(s2.MPI_SOURCE == 0);
389 check(s2.MPI_TAG == 5);
390 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
391 check(msg == MPI_MESSAGE_NULL);
394 /* test 9: mprobe+mrecv LARGE */
396 for (i = 0; i < LARGE_SZ; i++)
398 MPI_Send(sendbuf, LARGE_SZ, MPI_INT, 1, 5, MPI_COMM_WORLD);
401 memset(&s1, 0xab, sizeof(MPI_Status));
402 memset(&s2, 0xab, sizeof(MPI_Status));
403 /* the error field should remain unmodified */
404 s1.MPI_ERROR = MPI_ERR_DIMS;
405 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
407 msg = MPI_MESSAGE_NULL;
408 MPI_Mprobe(0, 5, MPI_COMM_WORLD, &msg, &s1);
409 check(s1.MPI_SOURCE == 0);
410 check(s1.MPI_TAG == 5);
411 check(s1.MPI_ERROR == MPI_ERR_DIMS);
412 check(msg != MPI_MESSAGE_NULL);
415 MPI_Get_count(&s1, MPI_INT, &count);
416 check(count == LARGE_SZ);
418 memset(recvbuf, 0xFF, LARGE_SZ * sizeof(int));
419 MPI_Mrecv(recvbuf, count, MPI_INT, &msg, &s2);
420 for (i = 0; i < LARGE_SZ; i++)
421 check(recvbuf[i] == i);
422 check(s2.MPI_SOURCE == 0);
423 check(s2.MPI_TAG == 5);
424 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
425 check(msg == MPI_MESSAGE_NULL);
428 /* test 10: mprobe+mrecv noncontiguous datatype */
429 MPI_Type_vector(2, 1, 4, MPI_INT, &vectype);
430 MPI_Type_commit(&vectype);
432 memset(sendbuf, 0, 8 * sizeof(int));
433 sendbuf[0] = 0xdeadbeef;
434 sendbuf[4] = 0xfeedface;
435 MPI_Send(sendbuf, 1, vectype, 1, 5, MPI_COMM_WORLD);
438 memset(&s1, 0xab, sizeof(MPI_Status));
439 memset(&s2, 0xab, sizeof(MPI_Status));
440 /* the error field should remain unmodified */
441 s1.MPI_ERROR = MPI_ERR_DIMS;
442 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
444 msg = MPI_MESSAGE_NULL;
445 MPI_Mprobe(0, 5, MPI_COMM_WORLD, &msg, &s1);
446 check(s1.MPI_SOURCE == 0);
447 check(s1.MPI_TAG == 5);
448 check(s1.MPI_ERROR == MPI_ERR_DIMS);
449 check(msg != MPI_MESSAGE_NULL);
452 MPI_Get_count(&s1, vectype, &count);
455 memset(recvbuf, 0, 8 * sizeof(int));
456 MPI_Mrecv(recvbuf, 1, vectype, &msg, &s2);
457 check(recvbuf[0] == 0xdeadbeef);
458 for (i = 1; i < 4; i++)
459 check(recvbuf[i] == 0);
460 check(recvbuf[4] = 0xfeedface);
461 for (i = 5; i < 8; i++)
462 check(recvbuf[i] == 0);
463 check(s2.MPI_SOURCE == 0);
464 check(s2.MPI_TAG == 5);
465 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
466 check(msg == MPI_MESSAGE_NULL);
468 MPI_Type_free(&vectype);
470 /* test 11: mprobe+mrecv noncontiguous datatype LARGE */
471 MPI_Type_vector(LARGE_DIM, LARGE_DIM - 1, LARGE_DIM, MPI_INT, &vectype);
472 MPI_Type_commit(&vectype);
474 for (i = 0; i < LARGE_SZ; i++)
476 MPI_Send(sendbuf, 1, vectype, 1, 5, MPI_COMM_WORLD);
481 memset(&s1, 0xab, sizeof(MPI_Status));
482 memset(&s2, 0xab, sizeof(MPI_Status));
483 /* the error field should remain unmodified */
484 s1.MPI_ERROR = MPI_ERR_DIMS;
485 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
487 msg = MPI_MESSAGE_NULL;
488 MPI_Mprobe(0, 5, MPI_COMM_WORLD, &msg, &s1);
489 check(s1.MPI_SOURCE == 0);
490 check(s1.MPI_TAG == 5);
491 check(s1.MPI_ERROR == MPI_ERR_DIMS);
492 check(msg != MPI_MESSAGE_NULL);
495 MPI_Get_count(&s1, vectype, &count);
498 memset(recvbuf, 0, LARGE_SZ * sizeof(int));
499 MPI_Mrecv(recvbuf, 1, vectype, &msg, &s2);
500 for (i = 0; i < LARGE_DIM; i++) {
502 for (j = 0; j < LARGE_DIM - 1; j++) {
503 check(recvbuf[idx] == idx);
506 check(recvbuf[idx++] == 0);
508 check(s2.MPI_SOURCE == 0);
509 check(s2.MPI_TAG == 5);
510 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
511 check(msg == MPI_MESSAGE_NULL);
513 MPI_Type_free(&vectype);
515 /* test 12: order test */
517 MPI_Request lrequest[2];
518 sendbuf[0] = 0xdeadbeef;
519 sendbuf[1] = 0xfeedface;
520 sendbuf[2] = 0xdeadbeef;
521 sendbuf[3] = 0xfeedface;
522 sendbuf[4] = 0xdeadbeef;
523 sendbuf[5] = 0xfeedface;
524 MPI_Isend(&sendbuf[0], 4, MPI_INT, 1, 6, MPI_COMM_WORLD, &lrequest[0]);
525 MPI_Isend(&sendbuf[4], 2, MPI_INT, 1, 6, MPI_COMM_WORLD, &lrequest[1]);
526 MPI_Waitall(2, &lrequest[0], MPI_STATUSES_IGNORE);
529 memset(&s1, 0xab, sizeof(MPI_Status));
530 memset(&s2, 0xab, sizeof(MPI_Status));
531 /* the error field should remain unmodified */
532 s1.MPI_ERROR = MPI_ERR_DIMS;
533 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
535 msg = MPI_MESSAGE_NULL;
536 MPI_Mprobe(0, 6, MPI_COMM_WORLD, &msg, &s1);
537 check(s1.MPI_SOURCE == 0);
538 check(s1.MPI_TAG == 6);
539 check(s1.MPI_ERROR == MPI_ERR_DIMS);
540 check(msg != MPI_MESSAGE_NULL);
543 MPI_Get_count(&s1, MPI_INT, &count);
546 recvbuf[0] = 0x01234567;
547 recvbuf[1] = 0x89abcdef;
548 MPI_Recv(recvbuf, 2, MPI_INT, 0, 6, MPI_COMM_WORLD, &s2);
549 check(s2.MPI_SOURCE == 0);
550 check(s2.MPI_TAG == 6);
551 check(recvbuf[0] == 0xdeadbeef);
552 check(recvbuf[1] == 0xfeedface);
554 recvbuf[0] = 0x01234567;
555 recvbuf[1] = 0x89abcdef;
556 recvbuf[2] = 0x01234567;
557 recvbuf[3] = 0x89abcdef;
558 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
560 MPI_Mrecv(recvbuf, count, MPI_INT, &msg, &s2);
561 check(recvbuf[0] == 0xdeadbeef);
562 check(recvbuf[1] == 0xfeedface);
563 check(recvbuf[2] == 0xdeadbeef);
564 check(recvbuf[3] == 0xfeedface);
565 check(s2.MPI_SOURCE == 0);
566 check(s2.MPI_TAG == 6);
567 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
568 check(msg == MPI_MESSAGE_NULL);
574 /* TODO MPI_ANY_SOURCE and MPI_ANY_TAG should be tested as well */
575 /* TODO a full range of message sizes should be tested too */
576 /* TODO threaded tests are also needed, but they should go in a separate
579 /* simple test to ensure that c2f/f2c routines are present (initially missed
582 MPI_Fint f_handle = 0xdeadbeef;
583 f_handle = MPI_Message_c2f(MPI_MESSAGE_NULL);
584 msg = MPI_Message_f2c(f_handle);
585 check(f_handle != 0xdeadbeef);
586 check(msg == MPI_MESSAGE_NULL);
588 /* PMPI_ versions should also exists */
589 f_handle = 0xdeadbeef;
590 f_handle = PMPI_Message_c2f(MPI_MESSAGE_NULL);
591 msg = PMPI_Message_f2c(f_handle);
592 check(f_handle != 0xdeadbeef);
593 check(msg == MPI_MESSAGE_NULL);
597 MPI_Reduce((rank == 0 ? MPI_IN_PLACE : &errs), &errs, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
600 printf("found %d errors\n", errs);
603 printf(" No errors\n");