Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add new entry in Release_Notes.
[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 /* assert-like macro that bumps the err count and emits a message */
14 #define check(x_)                                                                 \
15     do {                                                                          \
16         if (!(x_)) {                                                              \
17             ++errs;                                                               \
18             if (errs < 10) {                                                      \
19                 fprintf(stderr, "check failed: (%s), line %d\n", #x_, __LINE__); \
20             }                                                                     \
21         }                                                                         \
22     } while (0)
23
24 int main(int argc, char **argv)
25 {
26     int errs = 0;
27     int i;
28     int rank, size, lrank, lsize, rsize;
29     int buf[2];
30     MPI_Comm newcomm, ic, localcomm, stagger_comm;
31     MPI_Request rreq;
32
33     MPI_Init(&argc, &argv);
34
35     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
36     MPI_Comm_size(MPI_COMM_WORLD, &size);
37
38     if (size < 2) {
39         printf("this test requires at least 2 processes\n");
40         MPI_Abort(MPI_COMM_WORLD, 1);
41     }
42
43     /* test plan: make rank 0 wait in a blocking recv until all other processes
44      * have posted their MPI_Comm_idup ops, then post last.  Should ensure that
45      * idup doesn't block on the non-zero ranks, otherwise we'll get a deadlock.
46      */
47
48     if (rank == 0) {
49         for (i = 1; i < size; ++i) {
50             buf[0] = 0x01234567;
51             buf[1] = 0x89abcdef;
52             MPI_Recv(buf, 2, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
53         }
54         MPI_Comm_idup(MPI_COMM_WORLD, &newcomm, &rreq);
55         MPI_Wait(&rreq, MPI_STATUS_IGNORE);
56     }
57     else {
58         MPI_Comm_idup(MPI_COMM_WORLD, &newcomm, &rreq);
59         buf[0] = rank;
60         buf[1] = size + rank;
61         MPI_Ssend(buf, 2, MPI_INT, 0, 0, MPI_COMM_WORLD);
62         MPI_Wait(&rreq, MPI_STATUS_IGNORE);
63     }
64
65     /* do some communication to make sure that newcomm works */
66     buf[0] = rank;
67     buf[1] = 0xfeedface;
68     MPI_Allreduce(&buf[0], &buf[1], 1, MPI_INT, MPI_SUM, newcomm);
69     check(buf[1] == (size * (size - 1) / 2));
70
71     MPI_Comm_free(&newcomm);
72
73     /* now construct an intercomm and make sure we can dup that too */
74     MPI_Comm_split(MPI_COMM_WORLD, rank % 2, rank, &localcomm);
75     MPI_Intercomm_create(localcomm, 0, MPI_COMM_WORLD, (rank == 0 ? 1 : 0), 1234, &ic);
76
77     /* Create a communicator on just the "right hand group" of the intercomm in
78      * order to make it more likely to catch bugs related to incorrectly
79      * swapping the context_id and recvcontext_id in the idup code. */
80     stagger_comm = MPI_COMM_NULL;
81     if (rank % 2) {
82         MPI_Comm_dup(localcomm, &stagger_comm);
83     }
84
85     MPI_Comm_rank(ic, &lrank);
86     MPI_Comm_size(ic, &lsize);
87     MPI_Comm_remote_size(ic, &rsize);
88
89     /* Similar to above pattern, but all non-local-rank-0 processes send to
90      * remote rank 0.  Both sides participate in this way. */
91     if (lrank == 0) {
92         for (i = 1; i < rsize; ++i) {
93             buf[0] = 0x01234567;
94             buf[1] = 0x89abcdef;
95             MPI_Recv(buf, 2, MPI_INT, i, 0, ic, MPI_STATUS_IGNORE);
96         }
97         MPI_Comm_idup(ic, &newcomm, &rreq);
98         MPI_Wait(&rreq, MPI_STATUS_IGNORE);
99     }
100     else {
101         MPI_Comm_idup(ic, &newcomm, &rreq);
102         buf[0] = lrank;
103         buf[1] = lsize + lrank;
104         MPI_Ssend(buf, 2, MPI_INT, 0, 0, ic);
105         MPI_Wait(&rreq, MPI_STATUS_IGNORE);
106     }
107
108     /* do some communication to make sure that newcomm works */
109     buf[0] = lrank;
110     buf[1] = 0xfeedface;
111     MPI_Allreduce(&buf[0], &buf[1], 1, MPI_INT, MPI_SUM, newcomm);
112     check(buf[1] == (rsize * (rsize - 1) / 2));
113
114     /* free this down here, not before idup, otherwise it will undo our
115      * stagger_comm work */
116     MPI_Comm_free(&localcomm);
117
118     if (stagger_comm != MPI_COMM_NULL) {
119         MPI_Comm_free(&stagger_comm);
120     }
121     MPI_Comm_free(&newcomm);
122     MPI_Comm_free(&ic);
123
124     MPI_Reduce((rank == 0 ? MPI_IN_PLACE : &errs), &errs, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
125     if (rank == 0) {
126         if (errs) {
127             printf("found %d errors\n", errs);
128         }
129         else {
130             printf(" No errors\n");
131         }
132     }
133
134     MPI_Finalize();
135
136     return 0;
137 }