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 / icsplit.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_split 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;
23     MPI_Comm intercomm, newcomm;
24
25     MTest_Init( &argc, &argv );
26
27     MPI_Comm_size( MPI_COMM_WORLD, &size );
28     if (size < 4) {
29         printf( "This test requires at least 4 processes\n" );
30         MPI_Abort( MPI_COMM_WORLD, 1 );
31     }
32
33     while (MTestGetIntercomm( &intercomm, &isLeft, 2 )) {
34         int key, color;
35
36         if (intercomm == MPI_COMM_NULL) continue;
37
38         /* Split this intercomm.  The new intercomms contain the 
39            processes that had odd (resp even) rank in their local group
40            in the original intercomm */
41         MTestPrintfMsg( 1, "Created intercomm %s\n", MTestGetIntercommName() );
42         MPI_Comm_rank( intercomm, &key );
43         color = (key % 2);
44         MPI_Comm_split( intercomm, color, key, &newcomm );
45         /* Make sure that the new communicator has the appropriate pieces */
46         if (newcomm != MPI_COMM_NULL) {
47             int orig_rsize, orig_size, new_rsize, new_size;
48             int predicted_size, flag, commok=1;
49
50             MPI_Comm_test_inter( intercomm, &flag );
51             if (!flag) {
52                 errs++;
53                 printf( "Output communicator is not an intercomm\n" );
54                 commok = 0;
55             }
56
57             MPI_Comm_remote_size( intercomm, &orig_rsize );
58             MPI_Comm_remote_size( newcomm, &new_rsize );
59             MPI_Comm_size( intercomm, &orig_size );
60             MPI_Comm_size( newcomm, &new_size );
61             /* The local size is 1/2 the original size, +1 if the 
62                size was odd and the color was even.  More precisely,
63                let n be the orig_size.  Then
64                                 color 0     color 1
65                orig size even    n/2         n/2
66                orig size odd     (n+1)/2     n/2
67
68                However, since these are integer valued, if n is even,
69                then (n+1)/2 = n/2, so this table is much simpler:
70                                 color 0     color 1
71                orig size even    (n+1)/2     n/2
72                orig size odd     (n+1)/2     n/2
73                
74             */
75             predicted_size = (orig_size + !color) / 2; 
76             if (predicted_size != new_size) {
77                 errs++;
78                 printf( "Predicted size = %d but found %d for %s (%d,%d)\n",
79                         predicted_size, new_size, MTestGetIntercommName(),
80                         orig_size, orig_rsize );
81                 commok = 0;
82             }
83             predicted_size = (orig_rsize + !color) / 2;
84             if (predicted_size != new_rsize) {
85                 errs++;
86                 printf( "Predicted remote size = %d but found %d for %s (%d,%d)\n",
87                         predicted_size, new_rsize, MTestGetIntercommName(), 
88                         orig_size, orig_rsize );
89                 commok = 0;
90             }
91             /* ... more to do */
92             if (commok) {
93                 errs += TestIntercomm( newcomm );
94             }
95         }
96         else {
97             int orig_rsize;
98             /* If the newcomm is null, then this means that remote group
99                for this color is of size zero (since all processes in this 
100                test have been given colors other than MPI_UNDEFINED).
101                Confirm that here */
102             /* FIXME: ToDo */
103             MPI_Comm_remote_size( intercomm, &orig_rsize );
104             if (orig_rsize == 1) {
105                 if (color == 0) {
106                     errs++;
107                     printf( "Returned null intercomm when non-null expected\n" );
108                 }
109             }
110         }
111         if (newcomm != MPI_COMM_NULL) 
112             MPI_Comm_free( &newcomm );
113         MPI_Comm_free( &intercomm );
114     }
115     MTest_Finalize(errs);
116
117     MPI_Finalize();
118
119     return 0;
120 }
121
122 /* FIXME: This is copied from iccreate.  It should be in one place */
123 int TestIntercomm( MPI_Comm comm )
124 {
125     int local_size, remote_size, rank, **bufs, *bufmem, rbuf[2], j;
126     int errs = 0, wrank, nsize;
127     char commname[MPI_MAX_OBJECT_NAME+1];
128     MPI_Request *reqs;
129
130     MPI_Comm_rank( MPI_COMM_WORLD, &wrank );
131     MPI_Comm_size( comm, &local_size );
132     MPI_Comm_remote_size( comm, &remote_size );
133     MPI_Comm_rank( comm, &rank );
134     MPI_Comm_get_name( comm, commname, &nsize );
135
136     MTestPrintfMsg( 1, "Testing communication on intercomm %s\n", commname );
137     
138     reqs = (MPI_Request *)malloc( remote_size * sizeof(MPI_Request) );
139     if (!reqs) {
140         printf( "[%d] Unable to allocated %d requests for testing intercomm %s\n", 
141                 wrank, remote_size, commname );
142         errs++;
143         return errs;
144     }
145     bufs = (int **) malloc( remote_size * sizeof(int *) );
146     if (!bufs) {
147         printf( "[%d] Unable to allocated %d int pointers for testing intercomm %s\n", 
148                 wrank, remote_size, commname );
149         errs++;
150         return errs;
151     }
152     bufmem = (int *) malloc( remote_size * 2 * sizeof(int) );
153     if (!bufmem) {
154         printf( "[%d] Unable to allocated %d int data for testing intercomm %s\n", 
155                 wrank, 2*remote_size, commname );
156         errs++;
157         return errs;
158     }
159
160     /* Each process sends a message containing its own rank and the
161        rank of the destination with a nonblocking send.  Because we're using
162        nonblocking sends, we need to use different buffers for each isend */
163     for (j=0; j<remote_size; j++) {
164         bufs[j]    = &bufmem[2*j];
165         bufs[j][0] = rank;
166         bufs[j][1] = j;
167         MPI_Isend( bufs[j], 2, MPI_INT, j, 0, comm, &reqs[j] );
168     }
169
170     for (j=0; j<remote_size; j++) {
171         MPI_Recv( rbuf, 2, MPI_INT, j, 0, comm, MPI_STATUS_IGNORE );
172         if (rbuf[0] != j) {
173             printf( "[%d] Expected rank %d but saw %d in %s\n", 
174                     wrank, j, rbuf[0], commname );
175             errs++;
176         }
177         if (rbuf[1] != rank) {
178             printf( "[%d] Expected target rank %d but saw %d from %d in %s\n", 
179                     wrank, rank, rbuf[1], j, commname );
180             errs++;
181         }
182     }
183     if (errs) 
184         fflush(stdout);
185     MPI_Waitall( remote_size, reqs, MPI_STATUSES_IGNORE );
186
187     free( reqs );
188     free( bufs );
189     free( bufmem );
190
191     return errs;
192 }