Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
4b3cedd92d608f4f77cae1b0f46448d318bc76bf
[simgrid.git] / teshsuite / smpi / mpich3-test / comm / iccreate.c
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  *
4  *  (C) 2007 by Argonne National Laboratory.
5  *      See COPYRIGHT in top-level directory.
6  */
7 #include "mpi.h"
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include "mpitest.h"
11
12 /*
13  * This program tests that MPI_Comm_create applies to intercommunicators;
14  * this is an extension added in MPI-2
15  */
16
17 int TestIntercomm( MPI_Comm );
18
19 int main( int argc, char *argv[] )
20 {
21     int errs = 0;
22     int size, isLeft, wrank;
23     MPI_Comm intercomm, newcomm;
24     MPI_Group oldgroup, newgroup;
25
26     MTest_Init( &argc, &argv );
27
28     MPI_Comm_size( MPI_COMM_WORLD, &size );
29     if (size < 4) {
30         printf( "This test requires at least 4 processes\n" );
31         MPI_Abort( MPI_COMM_WORLD, 1 );
32     }
33     MPI_Comm_rank( MPI_COMM_WORLD, &wrank );
34
35     while (MTestGetIntercomm( &intercomm, &isLeft, 2 )) {
36         int ranks[10], nranks, result;
37
38         if (intercomm == MPI_COMM_NULL) continue;
39
40         MPI_Comm_group( intercomm, &oldgroup );
41         ranks[0] = 0;
42         nranks   = 1;
43         MTestPrintfMsg( 1, "Creating a new intercomm 0-0\n" );
44         MPI_Group_incl( oldgroup, nranks, ranks, &newgroup );
45         MPI_Comm_create( intercomm, newgroup, &newcomm );
46
47         /* Make sure that the new communicator has the appropriate pieces */
48         if (newcomm != MPI_COMM_NULL) {
49             int new_rsize, new_size, flag, commok = 1;
50
51             MPI_Comm_set_name( newcomm, (char*)"Single rank in each group" );
52             MPI_Comm_test_inter( intercomm, &flag );
53             if (!flag) {
54                 errs++;
55                 printf( "[%d] Output communicator is not an intercomm\n",
56                         wrank );
57                 commok = 0;
58             }
59
60             MPI_Comm_remote_size( newcomm, &new_rsize );
61             MPI_Comm_size( newcomm, &new_size );
62             /* The new communicator has 1 process in each group */
63             if (new_rsize != 1) {
64                 errs++;
65                 printf( "[%d] Remote size is %d, should be one\n", 
66                         wrank, new_rsize );
67                 commok = 0;
68             }
69             if (new_size != 1) {
70                 errs++;
71                 printf( "[%d] Local size is %d, should be one\n", 
72                         wrank, new_size );
73                 commok = 0;
74             }
75             /* ... more to do */
76             if (commok) {
77                 errs += TestIntercomm( newcomm );
78             }
79         }
80         MPI_Group_free( &newgroup );
81         if (newcomm != MPI_COMM_NULL) {
82             MPI_Comm_free( &newcomm );
83         }
84
85         /* Now, do a sort of dup, using the original group */
86         MTestPrintfMsg( 1, "Creating a new intercomm (manual dup)\n" );
87         MPI_Comm_create( intercomm, oldgroup, &newcomm );
88         MPI_Comm_set_name( newcomm, (char*)"Dup of original" );
89         MTestPrintfMsg( 1, "Creating a new intercomm (manual dup (done))\n" );
90
91         MPI_Comm_compare( intercomm, newcomm, &result );
92         MTestPrintfMsg( 1, "Result of comm/intercomm compare is %d\n", result );
93         if (result != MPI_CONGRUENT) {
94             const char *rname=0;
95             errs++;
96             switch (result) {
97             case MPI_IDENT:     rname = "IDENT"; break;
98             case MPI_CONGRUENT: rname = "CONGRUENT"; break;
99             case MPI_SIMILAR:   rname = "SIMILAR"; break;
100             case MPI_UNEQUAL:   rname = "UNEQUAL"; break;
101             printf( "[%d] Expected MPI_CONGRUENT but saw %d (%s)", 
102                     wrank, result, rname ); fflush(stdout);
103             }
104         }
105         else {
106             /* Try to communication between each member of intercomm */
107             errs += TestIntercomm( newcomm );
108         }
109
110         if (newcomm != MPI_COMM_NULL) {
111             MPI_Comm_free(&newcomm);
112         }
113         /* test that an empty group in either side of the intercomm results in
114          * MPI_COMM_NULL for all members of the comm */
115         if (isLeft) {
116             /* left side reuses oldgroup, our local group in intercomm */
117             MPI_Comm_create(intercomm, oldgroup, &newcomm);
118         }
119         else {
120             /* right side passes MPI_GROUP_EMPTY */
121             MPI_Comm_create(intercomm, MPI_GROUP_EMPTY, &newcomm);
122         }
123         if (newcomm != MPI_COMM_NULL) {
124             printf("[%d] expected MPI_COMM_NULL, but got a different communicator\n", wrank); fflush(stdout);
125             errs++;
126         }
127
128         if (newcomm != MPI_COMM_NULL) {
129             MPI_Comm_free(&newcomm);
130         }
131         MPI_Group_free( &oldgroup );
132         MPI_Comm_free( &intercomm );
133     }
134
135     MTest_Finalize(errs);
136
137     MPI_Finalize();
138
139     return 0;
140 }
141
142 int TestIntercomm( MPI_Comm comm )
143 {
144     int local_size, remote_size, rank, **bufs, *bufmem, rbuf[2], j;
145     int errs = 0, wrank, nsize;
146     char commname[MPI_MAX_OBJECT_NAME+1];
147     MPI_Request *reqs;
148
149     MPI_Comm_rank( MPI_COMM_WORLD, &wrank );
150     MPI_Comm_size( comm, &local_size );
151     MPI_Comm_remote_size( comm, &remote_size );
152     MPI_Comm_rank( comm, &rank );
153     MPI_Comm_get_name( comm, commname, &nsize );
154
155     MTestPrintfMsg( 1, "Testing communication on intercomm '%s', remote_size=%d\n",
156                     commname, remote_size );
157
158     reqs = (MPI_Request *)malloc( remote_size * sizeof(MPI_Request) );
159     if (!reqs) {
160         printf( "[%d] Unable to allocated %d requests for testing intercomm %s\n", 
161                 wrank, remote_size, commname );
162         errs++;
163         return errs;
164     }
165     bufs = (int **) malloc( remote_size * sizeof(int *) );
166     if (!bufs) {
167         printf( "[%d] Unable to allocated %d int pointers for testing intercomm %s\n", 
168                 wrank, remote_size, commname );
169         errs++;
170         return errs;
171     }
172     bufmem = (int *) malloc( remote_size * 2 * sizeof(int) );
173     if (!bufmem) {
174         printf( "[%d] Unable to allocated %d int data for testing intercomm %s\n", 
175                 wrank, 2*remote_size, commname );
176         errs++;
177         return errs;
178     }
179
180     /* Each process sends a message containing its own rank and the
181        rank of the destination with a nonblocking send.  Because we're using
182        nonblocking sends, we need to use different buffers for each isend */
183     /* NOTE: the send buffer access restriction was relaxed in MPI-2.2, although
184        it doesn't really hurt to keep separate buffers for our purposes */
185     for (j=0; j<remote_size; j++) {
186         bufs[j]    = &bufmem[2*j];
187         bufs[j][0] = rank;
188         bufs[j][1] = j;
189         MPI_Isend( bufs[j], 2, MPI_INT, j, 0, comm, &reqs[j] );
190     }
191     MTestPrintfMsg( 2, "isends posted, about to recv\n" );
192
193     for (j=0; j<remote_size; j++) {
194         MPI_Recv( rbuf, 2, MPI_INT, j, 0, comm, MPI_STATUS_IGNORE );
195         if (rbuf[0] != j) {
196             printf( "[%d] Expected rank %d but saw %d in %s\n", 
197                     wrank, j, rbuf[0], commname );
198             errs++;
199         }
200         if (rbuf[1] != rank) {
201             printf( "[%d] Expected target rank %d but saw %d from %d in %s\n", 
202                     wrank, rank, rbuf[1], j, commname );
203             errs++;
204         }
205     }
206     if (errs) 
207         fflush(stdout);
208     MTestPrintfMsg( 2, "my recvs completed, about to waitall\n" );
209     MPI_Waitall( remote_size, reqs, MPI_STATUSES_IGNORE );
210
211     free( reqs );
212     free( bufs );
213     free( bufmem );
214
215     return errs;
216 }