Logo AND Algorithmique Numérique Distribuée

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