Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add new entry in Release_Notes.
[simgrid.git] / teshsuite / smpi / mpich3-test / coll / allred_float.c
1 /*
2  * Copyright (C) by Argonne National Laboratory
3  *     See COPYRIGHT in top-level directory
4  */
5 #include "mpi.h"
6 #include "mpitest.h"
7 #include <stdio.h>
8 #include <stdlib.h>
9
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
14  * floating point.
15  *
16  * This test checks when an inapproprate algorithms is used for floating
17  * point reduction.
18  */
19
20 /* single-precision float has roughly a precision of 7 decimal digits */
21 #define BIG 1e6
22 #define TINY 1e-2
23
24 #define N 8
25
26 float buf[N];
27
28 static void init_buf(int rank, int pos1, int pos2)
29 {
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.
34      */
35     for (int i = 0; i < N; i++) {
36         if (rank == pos1) {
37             buf[i] = BIG;
38         } else if (rank == pos2) {
39             buf[i] = -BIG;
40         } else {
41             buf[i] = TINY;
42         }
43     }
44 }
45
46 int main(int argc, char **argv)
47 {
48     int errs = 0;
49
50     MTest_Init(&argc, &argv);
51
52     int rank, size;
53     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
54     MPI_Comm_size(MPI_COMM_WORLD, &size);
55
56     if (size < 3) {
57         printf("At least 3 processes required. More (e.g. 10) is recommended.\n");
58         MPI_Abort(MPI_COMM_WORLD, 1);
59     }
60
61     for (int pos1 = 0; pos1 < size; pos1++) {
62         for (int pos2 = pos1 + 1; pos2 < size; pos2++) {
63             init_buf(rank, pos1, pos2);
64
65             MPI_Allreduce(MPI_IN_PLACE, buf, N, MPI_FLOAT, MPI_SUM, MPI_COMM_WORLD);
66
67             float *check_buf=NULL;
68             if (rank == 0) {
69                 check_buf = malloc(N * size * sizeof(float));
70             }
71             MPI_Gather(buf, N, MPI_FLOAT, check_buf, N, MPI_FLOAT, 0, MPI_COMM_WORLD);
72
73             if (rank == 0) {
74                 MTestPrintfMsg(1, "BIG positions = (%d, %d), result = [", pos1, pos2);
75                 for (int j = 0; j < N; j++) {
76                     MTestPrintfMsg(1, "%f ", buf[j]);
77                 }
78                 MTestPrintfMsg(1, "]\n");
79
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) {
83                             if (errs < 10) {
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]);
86                             }
87                             errs++;
88                         }
89                     }
90                 }
91                 free(check_buf);
92             }
93         }
94     }
95
96     MTest_Finalize(errs);
97     return MTestReturnValue(errs);
98 }