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 /* This is a temporary #ifdef to control whether we test this functionality. A
14 * configure-test or similar would be better. Eventually the MPI-3 standard
15 * will be released and this can be gated on a MPI_VERSION check */
16 #if !defined(USE_STRICT_MPI) && defined(MPICH)
20 /* assert-like macro that bumps the err count and emits a message */
26 fprintf(stderr, "check failed: (%s), line %d\n", #x_, __LINE__); \
31 int main(int argc, char **argv)
35 int rank, size, lrank, lsize, rsize;
37 MPI_Comm newcomm, ic, localcomm, stagger_comm;
40 MPI_Init(&argc, &argv);
42 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
43 MPI_Comm_size(MPI_COMM_WORLD, &size);
46 printf("this test requires at least 2 processes\n");
47 MPI_Abort(MPI_COMM_WORLD, 1);
52 /* test plan: make rank 0 wait in a blocking recv until all other processes
53 * have posted their MPI_Comm_idup ops, then post last. Should ensure that
54 * idup doesn't block on the non-zero ranks, otherwise we'll get a deadlock.
58 for (i = 1; i < size; ++i) {
61 MPI_Recv(buf, 2, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
63 MPI_Comm_idup(MPI_COMM_WORLD, &newcomm, &rreq);
64 MPI_Wait(&rreq, MPI_STATUS_IGNORE);
67 MPI_Comm_idup(MPI_COMM_WORLD, &newcomm, &rreq);
70 MPI_Ssend(buf, 2, MPI_INT, 0, 0, MPI_COMM_WORLD);
71 MPI_Wait(&rreq, MPI_STATUS_IGNORE);
74 /* do some communication to make sure that newcomm works */
77 MPI_Allreduce(&buf[0], &buf[1], 1, MPI_INT, MPI_SUM, newcomm);
78 check(buf[1] == (size * (size-1) / 2));
80 MPI_Comm_free(&newcomm);
82 /* now construct an intercomm and make sure we can dup that too */
83 MPI_Comm_split(MPI_COMM_WORLD, rank % 2, rank, &localcomm);
84 MPI_Intercomm_create(localcomm, 0, MPI_COMM_WORLD, (rank == 0 ? 1 : 0), 1234, &ic);
86 /* Create a communicator on just the "right hand group" of the intercomm in
87 * order to make it more likely to catch bugs related to incorrectly
88 * swapping the context_id and recvcontext_id in the idup code. */
89 stagger_comm = MPI_COMM_NULL;
91 MPI_Comm_dup(localcomm, &stagger_comm);
94 MPI_Comm_rank(ic, &lrank);
95 MPI_Comm_size(ic, &lsize);
96 MPI_Comm_remote_size(ic, &rsize);
98 /* Similar to above pattern, but all non-local-rank-0 processes send to
99 * remote rank 0. Both sides participate in this way. */
101 for (i = 1; i < rsize; ++i) {
104 MPI_Recv(buf, 2, MPI_INT, i, 0, ic, MPI_STATUS_IGNORE);
106 MPI_Comm_idup(ic, &newcomm, &rreq);
107 MPI_Wait(&rreq, MPI_STATUS_IGNORE);
110 MPI_Comm_idup(ic, &newcomm, &rreq);
112 buf[1] = lsize + lrank;
113 MPI_Ssend(buf, 2, MPI_INT, 0, 0, ic);
114 MPI_Wait(&rreq, MPI_STATUS_IGNORE);
117 /* do some communication to make sure that newcomm works */
120 MPI_Allreduce(&buf[0], &buf[1], 1, MPI_INT, MPI_SUM, newcomm);
121 check(buf[1] == (rsize * (rsize-1) / 2));
123 /* free this down here, not before idup, otherwise it will undo our
124 * stagger_comm work */
125 MPI_Comm_free(&localcomm);
127 if (stagger_comm != MPI_COMM_NULL) {
128 MPI_Comm_free(&stagger_comm);
130 MPI_Comm_free(&newcomm);
133 #endif /* TEST_IDUP */
135 MPI_Reduce((rank == 0 ? MPI_IN_PLACE : &errs), &errs, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
138 printf("found %d errors\n", errs);
141 printf(" No errors\n");