File: cmsplit2.c

package info (click to toggle)
mpich 3.3-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 131,836 kB
  • sloc: ansic: 975,868; cpp: 57,437; f90: 53,762; perl: 19,562; xml: 12,464; sh: 12,303; fortran: 7,875; makefile: 7,078; ruby: 126; java: 100; python: 98; lisp: 19; php: 8; sed: 4
file content (131 lines) | stat: -rw-r--r-- 5,075 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
 *  (C) 2011 by Argonne National Laboratory.
 *      See COPYRIGHT in top-level directory.
 */

/* This test ensures that MPI_Comm_split breaks ties in key values by using the
 * original rank in the input communicator.  This typically corresponds to
 * the difference between using a stable sort or using an unstable sort.
 *
 * It checks all sizes from 1..comm_size(world)-1, so this test does not need to
 * be run multiple times at process counts from a higher-level test driver. */

#include <stdio.h>
#include <stdlib.h>
#include "mpi.h"
#include "mpitest.h"

#define ERRLIMIT (10)

#define my_assert(cond_)                                     \
    do {                                                     \
        if (!(cond_)) {                                      \
            if (errs < ERRLIMIT)                             \
                printf("assertion \"%s\" failed\n", #cond_); \
            ++errs;                                          \
        }                                                    \
    } while (0)

int main(int argc, char **argv)
{
    int i, j, pos, modulus, cs, rank, size;
    int wrank, wsize;
    int newrank, newsize;
    int errs = 0;
    int key;
    int *oldranks = NULL;
    int *identity = NULL;
    int verbose = 0;
    MPI_Comm comm, splitcomm;
    MPI_Group wgroup, newgroup;

    MTest_Init(&argc, &argv);

    if (getenv("MPITEST_VERBOSE"))
        verbose = 1;

    MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
    MPI_Comm_size(MPI_COMM_WORLD, &wsize);

    oldranks = malloc(wsize * sizeof(int));
    identity = malloc(wsize * sizeof(int));
    for (i = 0; i < wsize; ++i) {
        identity[i] = i;
    }

    for (cs = 1; cs <= wsize; ++cs) {
        /* yes, we are using comm_split to test comm_split, but this test is
         * mainly about ensuring that the stable sort behavior is correct, not
         * about whether the partitioning by color behavior is correct */
        MPI_Comm_split(MPI_COMM_WORLD, (wrank < cs ? 0 : MPI_UNDEFINED), wrank, &comm);
        if (comm != MPI_COMM_NULL) {
            MPI_Comm_rank(comm, &rank);
            MPI_Comm_size(comm, &size);

            for (modulus = 1; modulus <= size; ++modulus) {
                /* Divide all ranks into one of "modulus" equivalence classes.  Ranks in
                 * output comm will be ordered first by class, then within the class by
                 * rank in comm world. */
                key = rank % modulus;

                /* all pass same color, variable keys */
                MPI_Comm_split(comm, 5, key, &splitcomm);
                MPI_Comm_rank(splitcomm, &newrank);
                MPI_Comm_size(splitcomm, &newsize);
                my_assert(newsize == size);

                MPI_Comm_group(MPI_COMM_WORLD, &wgroup);
                MPI_Comm_group(splitcomm, &newgroup);
                int gsize;
                MPI_Group_size(newgroup, &gsize);
                MPI_Group_translate_ranks(newgroup, size, identity, wgroup, oldranks);
                MPI_Group_free(&wgroup);
                MPI_Group_free(&newgroup);

                if (splitcomm != MPI_COMM_NULL)
                    MPI_Comm_free(&splitcomm);

                /* now check that comm_split broke any ties correctly */
                if (rank == 0) {
                    if (verbose) {
                        /* debugging code that is useful when the test fails */
                        printf("modulus=%d oldranks={", modulus);
                        for (i = 0; i < size - 1; ++i) {
                            printf("%d,", oldranks[i]);
                        }
                        printf("%d} keys={", oldranks[i]);
                        for (i = 0; i < size - 1; ++i) {
                            printf("%d,", i % modulus);
                        }
                        printf("%d}\n", i % modulus);
                    }

                    pos = 0;
                    for (i = 0; i < modulus; ++i) {
                        /* there's probably a better way to write these loop bounds and
                         * indices, but this is the first (correct) way that occurred to me */
                        for (j = 0; j < (size / modulus + (i < size % modulus ? 1 : 0)); ++j) {
                            if (errs < ERRLIMIT && oldranks[pos] != i + modulus * j) {
                                printf
                                    ("size=%d i=%d j=%d modulus=%d pos=%d i+modulus*j=%d oldranks[pos]=%d\n",
                                     size, i, j, modulus, pos, i + modulus * j, oldranks[pos]);
                            }
                            my_assert(oldranks[pos] == i + modulus * j);
                            ++pos;
                        }
                    }
                }
            }
            MPI_Comm_free(&comm);
        }
    }

    if (oldranks != NULL)
        free(oldranks);
    if (identity != NULL)
        free(identity);

    MTest_Finalize(errs);
    return MTestReturnValue(errs);
}