Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'hypervisor' of git+ssh://scm.gforge.inria.fr//gitroot/simgrid/simgrid...
[simgrid.git] / teshsuite / smpi / mpich3-test / comm / comm_idup.c
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  *  (C) 2012 by Argonne National Laboratory.
4  *      See COPYRIGHT in top-level directory.
5  */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "mpi.h"
11 #include "mpitest.h"
12
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)
17 #define TEST_IDUP 1
18 #endif
19
20 /* assert-like macro that bumps the err count and emits a message */
21 #define check(x_)                                                                 \
22     do {                                                                          \
23         if (!(x_)) {                                                              \
24             ++errs;                                                               \
25             if (errs < 10) {                                                      \
26                 fprintf(stderr, "check failed: (%s), line %d\n", #x_, __LINE__); \
27             }                                                                     \
28         }                                                                         \
29     } while (0)
30
31 int main(int argc, char **argv)
32 {
33     int errs = 0;
34     int i;
35     int rank, size, lrank, lsize, rsize;
36     int buf[2];
37     MPI_Comm newcomm, ic, localcomm, stagger_comm;
38     MPI_Request rreq;
39
40     MPI_Init(&argc, &argv);
41
42     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
43     MPI_Comm_size(MPI_COMM_WORLD, &size);
44
45     if (size < 2) {
46         printf("this test requires at least 2 processes\n");
47         MPI_Abort(MPI_COMM_WORLD, 1);
48     }
49
50 #ifdef TEST_IDUP
51
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.
55      */
56
57     if (rank == 0) {
58         for (i = 1; i < size; ++i) {
59             buf[0] = 0x01234567;
60             buf[1] = 0x89abcdef;
61             MPI_Recv(buf, 2, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
62         }
63         MPI_Comm_idup(MPI_COMM_WORLD, &newcomm, &rreq);
64         MPI_Wait(&rreq, MPI_STATUS_IGNORE);
65     }
66     else {
67         MPI_Comm_idup(MPI_COMM_WORLD, &newcomm, &rreq);
68         buf[0] = rank;
69         buf[1] = size + rank;
70         MPI_Ssend(buf, 2, MPI_INT, 0, 0, MPI_COMM_WORLD);
71         MPI_Wait(&rreq, MPI_STATUS_IGNORE);
72     }
73
74     /* do some communication to make sure that newcomm works */
75     buf[0] = rank;
76     buf[1] = 0xfeedface;
77     MPI_Allreduce(&buf[0], &buf[1], 1, MPI_INT, MPI_SUM, newcomm);
78     check(buf[1] == (size * (size-1) / 2));
79
80     MPI_Comm_free(&newcomm);
81
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);
85
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;
90     if (rank % 2) {
91         MPI_Comm_dup(localcomm, &stagger_comm);
92     }
93
94     MPI_Comm_rank(ic, &lrank);
95     MPI_Comm_size(ic, &lsize);
96     MPI_Comm_remote_size(ic, &rsize);
97
98     /* Similar to above pattern, but all non-local-rank-0 processes send to
99      * remote rank 0.  Both sides participate in this way. */
100     if (lrank == 0) {
101         for (i = 1; i < rsize; ++i) {
102             buf[0] = 0x01234567;
103             buf[1] = 0x89abcdef;
104             MPI_Recv(buf, 2, MPI_INT, i, 0, ic, MPI_STATUS_IGNORE);
105         }
106         MPI_Comm_idup(ic, &newcomm, &rreq);
107         MPI_Wait(&rreq, MPI_STATUS_IGNORE);
108     }
109     else {
110         MPI_Comm_idup(ic, &newcomm, &rreq);
111         buf[0] = lrank;
112         buf[1] = lsize + lrank;
113         MPI_Ssend(buf, 2, MPI_INT, 0, 0, ic);
114         MPI_Wait(&rreq, MPI_STATUS_IGNORE);
115     }
116
117     /* do some communication to make sure that newcomm works */
118     buf[0] = lrank;
119     buf[1] = 0xfeedface;
120     MPI_Allreduce(&buf[0], &buf[1], 1, MPI_INT, MPI_SUM, newcomm);
121     check(buf[1] == (rsize * (rsize-1) / 2));
122
123     /* free this down here, not before idup, otherwise it will undo our
124      * stagger_comm work */
125     MPI_Comm_free(&localcomm);
126
127     if (stagger_comm != MPI_COMM_NULL) {
128         MPI_Comm_free(&stagger_comm);
129     }
130     MPI_Comm_free(&newcomm);
131     MPI_Comm_free(&ic);
132
133 #endif /* TEST_IDUP */
134
135     MPI_Reduce((rank == 0 ? MPI_IN_PLACE : &errs), &errs, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
136     if (rank == 0) {
137         if (errs) {
138             printf("found %d errors\n", errs);
139         }
140         else {
141             printf(" No errors\n");
142         }
143     }
144
145     MPI_Finalize();
146
147     return 0;
148 }
149