1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
3 * (C) 2011 by Argonne National Laboratory.
4 * See COPYRIGHT in top-level directory.
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.
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. */
20 #define my_assert(cond_) \
23 if (errs < ERRLIMIT) \
24 printf("assertion \"%s\" failed\n", #cond_); \
29 int main(int argc, char **argv)
31 int i, j, pos, modulus, cs, rank, size;
39 MPI_Comm comm, splitcomm;
40 MPI_Group wgroup, newgroup;
42 MPI_Init(&argc, &argv);
44 if (getenv("MPITEST_VERBOSE"))
47 MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
48 MPI_Comm_size(MPI_COMM_WORLD, &wsize);
50 oldranks = malloc(wsize * sizeof(int));
51 identity = malloc(wsize * sizeof(int));
52 for (i = 0; i < wsize; ++i) {
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);
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. */
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);
77 MPI_Comm_group(MPI_COMM_WORLD, &wgroup);
78 MPI_Comm_group(splitcomm, &newgroup);
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);
85 if (splitcomm != MPI_COMM_NULL)
86 MPI_Comm_free(&splitcomm);
88 /* now check that comm_split broke any ties correctly */
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]);
96 printf("%d} keys={", oldranks[i]);
97 for (i = 0; i < size - 1; ++i) {
98 printf("%d,", i % modulus);
100 printf("%d}\n", i % modulus);
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("size=%d i=%d j=%d modulus=%d pos=%d i+modulus*j=%d oldranks[pos]=%d\n",
110 size, i, j, modulus, pos, i+modulus*j, oldranks[pos]);
112 my_assert(oldranks[pos] == i+modulus*j);
118 MPI_Comm_free(&comm);
122 if (oldranks != NULL)
124 if (identity != NULL)
129 printf("found %d errors\n", errs);
131 printf(" No errors\n");