Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
reduce some tests duration as comm_create takes longer now (comms)
[simgrid.git] / teshsuite / smpi / mpich3-test / comm / cmsplit2.c
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  *  (C) 2011 by Argonne National Laboratory.
4  *      See COPYRIGHT in top-level directory.
5  */
6
7 /* This test ensures that MPI_Comm_split breaks ties in key values by using the
8  * original rank in the input communicator.  This typically corresponds to
9  * the difference between using a stable sort or using an unstable sort.
10  *
11  * It checks all sizes from 1..comm_size(world)-1, so this test does not need to
12  * be run multiple times at process counts from a higher-level test driver. */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include "mpi.h"
17
18 #define ERRLIMIT (10)
19
20 #define my_assert(cond_)                                     \
21     do {                                                     \
22         if (!(cond_)) {                                      \
23             if (errs < ERRLIMIT)                             \
24                 printf("assertion \"%s\" failed\n", #cond_); \
25             ++errs;                                          \
26         }                                                    \
27     } while (0)
28
29 int main(int argc, char **argv)
30 {
31     int i, j, pos, modulus, cs, rank, size;
32     int wrank, wsize;
33     int newrank, newsize;
34     int errs = 0;
35     int key;
36     int *oldranks = NULL;
37     int *identity = NULL;
38     int verbose = 0;
39     MPI_Comm comm, splitcomm;
40     MPI_Group wgroup, newgroup;
41
42     MPI_Init(&argc, &argv);
43
44     if (getenv("MPITEST_VERBOSE"))
45         verbose = 1;
46
47     MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
48     MPI_Comm_size(MPI_COMM_WORLD, &wsize);
49
50     oldranks = malloc(wsize * sizeof(int));
51     identity = malloc(wsize * sizeof(int));
52     for (i = 0; i < wsize; ++i) {
53         identity[i] = i;
54     }
55
56     for (cs = 1; cs <= wsize; ++cs) {
57         /* yes, we are using comm_split to test comm_split, but this test is
58          * mainly about ensuring that the stable sort behavior is correct, not
59          * about whether the partitioning by color behavior is correct */
60         MPI_Comm_split(MPI_COMM_WORLD, (wrank < cs ? 0 : MPI_UNDEFINED), wrank, &comm);
61         if (comm != MPI_COMM_NULL) {
62             MPI_Comm_rank(comm, &rank);
63             MPI_Comm_size(comm, &size);
64
65             for (modulus = 1; modulus <= size; ++modulus) {
66                 /* Divide all ranks into one of "modulus" equivalence classes.  Ranks in
67                  * output comm will be ordered first by class, then within the class by
68                  * rank in comm world. */
69                 key = rank % modulus;
70
71                 /* all pass same color, variable keys */
72                 MPI_Comm_split(comm, 5, key, &splitcomm);
73                 MPI_Comm_rank(splitcomm, &newrank);
74                 MPI_Comm_size(splitcomm, &newsize);
75                 my_assert(newsize == size);
76
77                 MPI_Comm_group(MPI_COMM_WORLD, &wgroup);
78                 MPI_Comm_group(splitcomm, &newgroup);
79                 int gsize;
80                 MPI_Group_size(newgroup, &gsize);
81                 MPI_Group_translate_ranks(newgroup, size, identity, wgroup, oldranks);
82                 MPI_Group_free(&wgroup);
83                 MPI_Group_free(&newgroup);
84
85                 if (splitcomm != MPI_COMM_NULL)
86                     MPI_Comm_free(&splitcomm);
87
88                 /* now check that comm_split broke any ties correctly */
89                 if (rank == 0) {
90                     if (verbose) {
91                         /* debugging code that is useful when the test fails */
92                         printf("modulus=%d oldranks={", modulus);
93                         for (i = 0; i < size - 1; ++i) {
94                             printf("%d,", oldranks[i]);
95                         }
96                         printf("%d} keys={", oldranks[i]);
97                         for (i = 0; i < size - 1; ++i) {
98                             printf("%d,", i % modulus);
99                         }
100                         printf("%d}\n", i % modulus);
101                     }
102
103                     pos = 0;
104                     for (i = 0; i < modulus; ++i) {
105                         /* there's probably a better way to write these loop bounds and
106                          * indices, but this is the first (correct) way that occurred to me */
107                         for (j = 0; j < (size / modulus + (i < size % modulus ? 1 : 0)); ++j) {
108                             if (errs < ERRLIMIT && oldranks[pos] != i + modulus * j) {
109                                 printf
110                                     ("size=%d i=%d j=%d modulus=%d pos=%d i+modulus*j=%d oldranks[pos]=%d\n",
111                                      size, i, j, modulus, pos, i + modulus * j, oldranks[pos]);
112                             }
113                             my_assert(oldranks[pos] == i + modulus * j);
114                             ++pos;
115                         }
116                     }
117                 }
118             }
119             MPI_Comm_free(&comm);
120         }
121     }
122
123     if (oldranks != NULL)
124         free(oldranks);
125     if (identity != NULL)
126         free(identity);
127
128     if (rank == 0) {
129         if (errs)
130             printf("found %d errors\n", errs);
131         else
132             printf(" No errors\n");
133     }
134
135     MPI_Finalize();
136     return 0;
137 }