2 * Copyright (C) by Argonne National Laboratory
3 * See COPYRIGHT in top-level directory
10 /* MPI_Allreduce need produce identical results on all ranks. This is
11 * particular challenging for floating point datatypes since computer
12 * floating point arithmetic do not follow associative law. This means
13 * certain algorithms that works for integers need to be excluded for
16 * This test checks when an inapproprate algorithms is used for floating
20 /* single-precision float has roughly a precision of 7 decimal digits */
28 static void init_buf(int rank, int pos1, int pos2)
30 /* Mix a pair of (BIG, -BIG) and TINY, the sum of array will be the sum of
31 * all TINYs if we add (BIG, -BIG) first, but different results following
32 * different associativity. A valid algorithm need to produce consistent
33 * results on all ranks.
35 for (int i = 0; i < N; i++) {
38 } else if (rank == pos2) {
46 int main(int argc, char **argv)
50 MTest_Init(&argc, &argv);
53 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
54 MPI_Comm_size(MPI_COMM_WORLD, &size);
57 printf("At least 3 processes required. More (e.g. 10) is recommended.\n");
58 MPI_Abort(MPI_COMM_WORLD, 1);
61 for (int pos1 = 0; pos1 < size; pos1++) {
62 for (int pos2 = pos1 + 1; pos2 < size; pos2++) {
63 init_buf(rank, pos1, pos2);
65 MPI_Allreduce(MPI_IN_PLACE, buf, N, MPI_FLOAT, MPI_SUM, MPI_COMM_WORLD);
69 check_buf = malloc(N * size * sizeof(float));
71 MPI_Gather(buf, N, MPI_FLOAT, check_buf, N, MPI_FLOAT, 0, MPI_COMM_WORLD);
74 MTestPrintfMsg(1, "BIG positions = (%d, %d), result = [", pos1, pos2);
75 for (int j = 0; j < N; j++) {
76 MTestPrintfMsg(1, "%f ", buf[j]);
78 MTestPrintfMsg(1, "]\n");
80 for (int i = 0; i < size; i++) {
81 for (int j = 0; j < N; j++) {
82 if (memcmp(&check_buf[i * N + j], &buf[j], sizeof(float)) != 0) {
84 printf("(%d - %d) Result [%d] from rank %d mismatch: %f != %f\n",
85 pos1, pos2, j, i, check_buf[i * N + j], buf[j]);
97 return MTestReturnValue(errs);