Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add new entry in Release_Notes.
[simgrid.git] / teshsuite / smpi / mpich3-test / coll / allred.c
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  *  (C) 2001 by Argonne National Laboratory.
4  *      See COPYRIGHT in top-level directory.
5  */
6 /*      Warning - this test will fail for MPI_PROD & maybe MPI_SUM
7  *        if more than 10 MPI processes are used.  Loss of precision
8  *        will occur as the number of processors is increased.
9  */
10
11 #include "mpi.h"
12 #include "mpitest.h"
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #ifdef HAVE_STDINT_H
17 #include <stdint.h>
18 #endif
19
20 int count, size, rank;
21 int cerrcnt;
22
23 struct int_test {
24     int a;
25     int b;
26 };
27 struct long_test {
28     long a;
29     int b;
30 };
31 struct short_test {
32     short a;
33     int b;
34 };
35 struct float_test {
36     float a;
37     int b;
38 };
39 struct double_test {
40     double a;
41     int b;
42 };
43
44 #define mpi_op2str(op)                   \
45     ((op == MPI_SUM) ? "MPI_SUM" :       \
46      (op == MPI_PROD) ? "MPI_PROD" :     \
47      (op == MPI_MAX) ? "MPI_MAX" :       \
48      (op == MPI_MIN) ? "MPI_MIN" :       \
49      (op == MPI_LOR) ? "MPI_LOR" :       \
50      (op == MPI_LXOR) ? "MPI_LXOR" :     \
51      (op == MPI_LAND) ? "MPI_LAND" :     \
52      (op == MPI_BOR) ? "MPI_BOR" :       \
53      (op == MPI_BAND) ? "MPI_BAND" :     \
54      (op == MPI_BXOR) ? "MPI_BXOR" :     \
55      (op == MPI_MAXLOC) ? "MPI_MAXLOC" : \
56      (op == MPI_MINLOC) ? "MPI_MINLOC" : \
57      "MPI_NO_OP")
58
59 /* calloc to avoid spurious valgrind warnings when "type" has padding bytes */
60 #define DECL_MALLOC_IN_OUT_SOL(type)                 \
61     type *in, *out, *sol;                            \
62     in  = (type *) calloc(count, sizeof(type));      \
63     out = (type *) calloc(count, sizeof(type));      \
64     sol = (type *) calloc(count, sizeof(type));
65
66 #define SET_INDEX_CONST(arr, val)               \
67     {                                           \
68         int i;                                  \
69         for (i = 0; i < count; i++)             \
70             arr[i] = val;                       \
71     }
72
73 #define SET_INDEX_SUM(arr, val)                 \
74     {                                           \
75         int i;                                  \
76         for (i = 0; i < count; i++)             \
77             arr[i] = i + val;                   \
78     }
79
80 #define SET_INDEX_FACTOR(arr, val)              \
81     {                                           \
82         int i;                                  \
83         for (i = 0; i < count; i++)             \
84             arr[i] = i * (val);                 \
85     }
86
87 #define SET_INDEX_POWER(arr, val)               \
88     {                                           \
89         int i, j;                               \
90         for (i = 0; i < count; i++) {           \
91             (arr)[i] = 1;                       \
92             for (j = 0; j < (val); j++)         \
93                 arr[i] *= i;                    \
94         }                                       \
95     }
96
97 #define ERROR_CHECK_AND_FREE(lerrcnt, mpi_type, mpi_op)                 \
98     do {                                                                \
99         char name[MPI_MAX_OBJECT_NAME] = {0};                           \
100         int len = 0;                                                    \
101         if (lerrcnt) {                                                  \
102             MPI_Type_get_name(mpi_type, name, &len);                    \
103             fprintf(stderr, "(%d) Error for type %s and op %s\n",       \
104                     rank, name, mpi_op2str(mpi_op));                    \
105         }                                                               \
106         free(in); free(out); free(sol);                                 \
107     } while (0)
108
109 /* The logic on the error check on MPI_Allreduce assumes that all
110    MPI_Allreduce routines return a failure if any do - this is sufficient
111    for MPI implementations that reject some of the valid op/datatype pairs
112    (and motivated this addition, as some versions of the IBM MPI
113    failed in just this way).
114 */
115 #define ALLREDUCE_AND_FREE(mpi_type, mpi_op, in, out, sol)              \
116     {                                                                   \
117         int i, rc, lerrcnt = 0;                                         \
118         rc = MPI_Allreduce(in, out, count, mpi_type, mpi_op, MPI_COMM_WORLD); \
119         if (rc) { lerrcnt++; cerrcnt++; MTestPrintError(rc); }        \
120         else {                                                          \
121           for (i = 0; i < count; i++) {                                   \
122               if (out[i] != sol[i]) {                                     \
123                   cerrcnt++;                                              \
124                   lerrcnt++;                                              \
125               }                                                           \
126            }                                                              \
127         }                                                               \
128         ERROR_CHECK_AND_FREE(lerrcnt, mpi_type, mpi_op);                \
129     }
130
131 #define STRUCT_ALLREDUCE_AND_FREE(mpi_type, mpi_op, in, out, sol)       \
132     {                                                                   \
133         int i, rc, lerrcnt = 0;                                         \
134         rc = MPI_Allreduce(in, out, count, mpi_type, mpi_op, MPI_COMM_WORLD); \
135         if (rc) { lerrcnt++; cerrcnt++; MTestPrintError(rc); }        \
136         else {                                                            \
137           for (i = 0; i < count; i++) {                                   \
138               if ((out[i].a != sol[i].a) || (out[i].b != sol[i].b)) {     \
139                   cerrcnt++;                                              \
140                   lerrcnt++;                                              \
141               }                                                           \
142             }                                                             \
143         }                                                               \
144         ERROR_CHECK_AND_FREE(lerrcnt, mpi_type, mpi_op);                \
145     }
146
147 #define SET_INDEX_STRUCT_CONST(arr, val, el)                    \
148     {                                                           \
149         int i;                                                  \
150         for (i = 0; i < count; i++)                             \
151             arr[i].el = val;                                    \
152     }
153
154 #define SET_INDEX_STRUCT_SUM(arr, val, el)                      \
155     {                                                           \
156         int i;                                                  \
157         for (i = 0; i < count; i++)                             \
158             arr[i].el = i + (val);                              \
159     }
160
161 #define sum_test1(type, mpi_type)                                       \
162     {                                                                   \
163         DECL_MALLOC_IN_OUT_SOL(type);                                   \
164         SET_INDEX_SUM(in, 0);                                           \
165         SET_INDEX_FACTOR(sol, size);                                    \
166         SET_INDEX_CONST(out, 0);                                        \
167         ALLREDUCE_AND_FREE(mpi_type, MPI_SUM, in, out, sol);            \
168     }
169
170 #define prod_test1(type, mpi_type)                                      \
171     {                                                                   \
172         DECL_MALLOC_IN_OUT_SOL(type);                                   \
173         SET_INDEX_SUM(in, 0);                                           \
174         SET_INDEX_POWER(sol, size);                                     \
175         SET_INDEX_CONST(out, 0);                                        \
176         ALLREDUCE_AND_FREE(mpi_type, MPI_PROD, in, out, sol);           \
177     }
178
179 #define max_test1(type, mpi_type)                                       \
180     {                                                                   \
181         DECL_MALLOC_IN_OUT_SOL(type);                                   \
182         SET_INDEX_SUM(in, rank);                                        \
183         SET_INDEX_SUM(sol, size - 1);                                   \
184         SET_INDEX_CONST(out, 0);                                        \
185         ALLREDUCE_AND_FREE(mpi_type, MPI_MAX, in, out, sol);            \
186     }
187
188 #define min_test1(type, mpi_type)                                       \
189     {                                                                   \
190         DECL_MALLOC_IN_OUT_SOL(type);                                   \
191         SET_INDEX_SUM(in, rank);                                        \
192         SET_INDEX_SUM(sol, 0);                                          \
193         SET_INDEX_CONST(out, 0);                                        \
194         ALLREDUCE_AND_FREE(mpi_type, MPI_MIN, in, out, sol);            \
195     }
196
197 #define const_test(type, mpi_type, mpi_op, val1, val2, val3)            \
198     {                                                                   \
199         DECL_MALLOC_IN_OUT_SOL(type);                                   \
200         SET_INDEX_CONST(in, (val1));                                    \
201         SET_INDEX_CONST(sol, (val2));                                   \
202         SET_INDEX_CONST(out, (val3));                                   \
203         ALLREDUCE_AND_FREE(mpi_type, mpi_op, in, out, sol);             \
204     }
205
206 #define lor_test1(type, mpi_type)                                       \
207     const_test(type, mpi_type, MPI_LOR, (rank & 0x1), (size > 1), 0)
208 #define lor_test2(type, mpi_type)                       \
209     const_test(type, mpi_type, MPI_LOR, 0, 0, 0)
210 #define lxor_test1(type, mpi_type)                                      \
211     const_test(type, mpi_type, MPI_LXOR, (rank == 1), (size > 1), 0)
212 #define lxor_test2(type, mpi_type)                      \
213     const_test(type, mpi_type, MPI_LXOR, 0, 0, 0)
214 #define lxor_test3(type, mpi_type)                      \
215     const_test(type, mpi_type, MPI_LXOR, 1, (size & 0x1), 0)
216 #define land_test1(type, mpi_type)                              \
217     const_test(type, mpi_type, MPI_LAND, (rank & 0x1), 0, 0)
218 #define land_test2(type, mpi_type)                      \
219     const_test(type, mpi_type, MPI_LAND, 1, 1, 0)
220 #define bor_test1(type, mpi_type)                                       \
221     const_test(type, mpi_type, MPI_BOR, (rank & 0x3), ((size < 3) ? size - 1 : 0x3), 0)
222 #define bxor_test1(type, mpi_type)                                      \
223     const_test(type, mpi_type, MPI_BXOR, (rank == 1) * 0xf0, (size > 1) * 0xf0, 0)
224 #define bxor_test2(type, mpi_type)                      \
225     const_test(type, mpi_type, MPI_BXOR, 0, 0, 0)
226 #define bxor_test3(type, mpi_type)                      \
227     const_test(type, mpi_type, MPI_BXOR, ~0, (size &0x1) ? ~0 : 0, 0)
228
229 #define band_test1(type, mpi_type)                                      \
230     {                                                                   \
231         DECL_MALLOC_IN_OUT_SOL(type);                                   \
232         if (rank == size-1) {                                           \
233             SET_INDEX_SUM(in, 0);                                       \
234         }                                                               \
235         else {                                                          \
236             SET_INDEX_CONST(in, ~0);                                    \
237         }                                                               \
238         SET_INDEX_SUM(sol, 0);                                          \
239         SET_INDEX_CONST(out, 0);                                        \
240         ALLREDUCE_AND_FREE(mpi_type, MPI_BAND, in, out, sol);           \
241     }
242
243 #define band_test2(type, mpi_type)                                      \
244     {                                                                   \
245         DECL_MALLOC_IN_OUT_SOL(type);                                   \
246         if (rank == size-1) {                                           \
247             SET_INDEX_SUM(in, 0);                                       \
248         }                                                               \
249         else {                                                          \
250             SET_INDEX_CONST(in, 0);                                     \
251         }                                                               \
252         SET_INDEX_CONST(sol, 0);                                        \
253         SET_INDEX_CONST(out, 0);                                        \
254         ALLREDUCE_AND_FREE(mpi_type, MPI_BAND, in, out, sol);           \
255     }
256
257 #define maxloc_test(type, mpi_type)                                     \
258     {                                                                   \
259         DECL_MALLOC_IN_OUT_SOL(type);                                   \
260         SET_INDEX_STRUCT_SUM(in, rank, a);                              \
261         SET_INDEX_STRUCT_CONST(in, rank, b);                            \
262         SET_INDEX_STRUCT_SUM(sol, size - 1, a);                         \
263         SET_INDEX_STRUCT_CONST(sol, size - 1, b);                       \
264         SET_INDEX_STRUCT_CONST(out, 0, a);                              \
265         SET_INDEX_STRUCT_CONST(out, -1, b);                             \
266         STRUCT_ALLREDUCE_AND_FREE(mpi_type, MPI_MAXLOC, in, out, sol);   \
267     }
268
269 #define minloc_test(type, mpi_type)                                     \
270     {                                                                   \
271         DECL_MALLOC_IN_OUT_SOL(type);                                   \
272         SET_INDEX_STRUCT_SUM(in, rank, a);                              \
273         SET_INDEX_STRUCT_CONST(in, rank, b);                            \
274         SET_INDEX_STRUCT_SUM(sol, 0, a);                                \
275         SET_INDEX_STRUCT_CONST(sol, 0, b);                              \
276         SET_INDEX_STRUCT_CONST(out, 0, a);                              \
277         SET_INDEX_STRUCT_CONST(out, -1, b);                             \
278         STRUCT_ALLREDUCE_AND_FREE(mpi_type, MPI_MINLOC, in, out, sol);  \
279     }
280
281 #if MTEST_HAVE_MIN_MPI_VERSION(2,2)
282 #define test_types_set_mpi_2_2_integer(op, post)                                                                       \
283   do {                                                                                                                 \
284     _XBT_CONCAT3(op, _test, post)(int8_t, MPI_INT8_T);                                                                 \
285     _XBT_CONCAT3(op, _test, post)(int16_t, MPI_INT16_T);                                                               \
286     _XBT_CONCAT3(op, _test, post)(int32_t, MPI_INT32_T);                                                               \
287     _XBT_CONCAT3(op, _test, post)(int64_t, MPI_INT64_T);                                                               \
288     _XBT_CONCAT3(op, _test, post)(uint8_t, MPI_UINT8_T);                                                               \
289     _XBT_CONCAT3(op, _test, post)(uint16_t, MPI_UINT16_T);                                                             \
290     _XBT_CONCAT3(op, _test, post)(uint32_t, MPI_UINT32_T);                                                             \
291     _XBT_CONCAT3(op, _test, post)(uint64_t, MPI_UINT64_T);                                                             \
292     _XBT_CONCAT3(op, _test, post)(MPI_Aint, MPI_AINT);                                                                 \
293     _XBT_CONCAT3(op, _test, post)(MPI_Offset, MPI_OFFSET);                                                             \
294   } while (0)
295 #else
296 #define test_types_set_mpi_2_2_integer(op,post) do { } while (0)
297 #endif
298
299 #if MTEST_HAVE_MIN_MPI_VERSION(3,0)
300 #define test_types_set_mpi_3_0_integer(op, post)                                                                       \
301   do {                                                                                                                 \
302     _XBT_CONCAT3(op, _test, post)(MPI_Count, MPI_COUNT);                                                               \
303   } while (0)
304 #else
305 #define test_types_set_mpi_3_0_integer(op,post) do { } while (0)
306 #endif
307
308 #define test_types_set1(op, post)                                                                                      \
309   {                                                                                                                    \
310     _XBT_CONCAT3(op, _test, post)(int, MPI_INT);                                                                       \
311     _XBT_CONCAT3(op, _test, post)(long, MPI_LONG);                                                                     \
312     _XBT_CONCAT3(op, _test, post)(short, MPI_SHORT);                                                                   \
313     _XBT_CONCAT3(op, _test, post)(unsigned short, MPI_UNSIGNED_SHORT);                                                 \
314     _XBT_CONCAT3(op, _test, post)(unsigned, MPI_UNSIGNED);                                                             \
315     _XBT_CONCAT3(op, _test, post)(unsigned long, MPI_UNSIGNED_LONG);                                                   \
316     _XBT_CONCAT3(op, _test, post)(unsigned char, MPI_UNSIGNED_CHAR);                                                   \
317     test_types_set_mpi_2_2_integer(op, post);                                                                          \
318     test_types_set_mpi_3_0_integer(op, post);                                                                          \
319   }
320
321 #define test_types_set2(op, post)                                                                                      \
322   {                                                                                                                    \
323     test_types_set1(op, post);                                                                                         \
324     _XBT_CONCAT3(op, _test, post)(float, MPI_FLOAT);                                                                   \
325     _XBT_CONCAT3(op, _test, post)(double, MPI_DOUBLE);                                                                 \
326   }
327
328 #define test_types_set3(op, post)                                                                                      \
329   {                                                                                                                    \
330     _XBT_CONCAT3(op, _test, post)(unsigned char, MPI_BYTE);                                                            \
331   }
332
333 /* Make sure that we test complex and double complex, even if long
334    double complex is not available */
335 #if defined(USE_LONG_DOUBLE_COMPLEX)
336
337 #if MTEST_HAVE_MIN_MPI_VERSION(2,2) && defined(HAVE_FLOAT__COMPLEX) \
338     && defined(HAVE_DOUBLE__COMPLEX) \
339     && defined(HAVE_LONG_DOUBLE__COMPLEX)
340 #define test_types_set4(op, post)                                                                                      \
341   do {                                                                                                                 \
342     _XBT_CONCAT3(op, _test, post)(float _Complex, MPI_C_FLOAT_COMPLEX);                                                \
343     _XBT_CONCAT3(op, _test, post)(double _Complex, MPI_C_DOUBLE_COMPLEX);                                              \
344     if (MPI_C_LONG_DOUBLE_COMPLEX != MPI_DATATYPE_NULL) {                                                              \
345       _XBT_CONCAT3(op, _test, post)(long double _Complex, MPI_C_LONG_DOUBLE_COMPLEX);                                  \
346     }                                                                                                                  \
347   } while (0)
348
349 #else
350 #define test_types_set4(op, post) do { } while (0)
351 #endif
352 #else
353
354 #if MTEST_HAVE_MIN_MPI_VERSION(2,2) && defined(HAVE_FLOAT__COMPLEX) \
355     && defined(HAVE_DOUBLE__COMPLEX)
356 #define test_types_set4(op, post)                                                                                      \
357   do {                                                                                                                 \
358     _XBT_CONCAT3(op, _test, post)(float _Complex, MPI_C_FLOAT_COMPLEX);                                                \
359     _XBT_CONCAT3(op, _test, post)(double _Complex, MPI_C_DOUBLE_COMPLEX);                                              \
360   } while (0)
361
362 #else
363 #define test_types_set4(op, post) do { } while (0)
364 #endif
365
366 #endif /* defined(USE_LONG_DOUBLE_COMPLEX) */
367
368 #if MTEST_HAVE_MIN_MPI_VERSION(2,2) && defined(HAVE__BOOL)
369 #define test_types_set5(op, post)                                                                                      \
370   do {                                                                                                                 \
371     _XBT_CONCAT3(op, _test, post)(_Bool, MPI_C_BOOL);                                                                  \
372   } while (0)
373
374 #else
375 #define test_types_set5(op, post) do { } while (0)
376 #endif
377
378 int main(int argc, char **argv)
379 {
380     MTest_Init(&argc, &argv);
381
382     MPI_Comm_size(MPI_COMM_WORLD, &size);
383     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
384
385     if (size < 2) {
386         fprintf(stderr, "At least 2 processes required\n");
387         MPI_Abort(MPI_COMM_WORLD, 1);
388     }
389
390     /* Set errors return so that we can provide better information
391      * should a routine reject one of the operand/datatype pairs */
392     MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
393
394     count = 10;
395     /* Allow an argument to override the count.
396      * Note that the product tests may fail if the count is very large.
397      */
398     if (argc >= 2) {
399         count = atoi(argv[1]);
400         if (count <= 0) {
401             fprintf(stderr, "Invalid count argument %s\n", argv[1]);
402             MPI_Abort(MPI_COMM_WORLD, 1);
403         }
404     }
405
406     test_types_set2(sum, 1);
407     test_types_set2(prod, 1);
408     test_types_set2(max, 1);
409     test_types_set2(min, 1);
410
411     test_types_set1(lor, 1);
412     test_types_set1(lor, 2);
413
414     test_types_set1(lxor, 1);
415     test_types_set1(lxor, 2);
416     test_types_set1(lxor, 3);
417
418     test_types_set1(land, 1);
419     test_types_set1(land, 2);
420
421     test_types_set1(bor, 1);
422     test_types_set1(band, 1);
423     test_types_set1(band, 2);
424
425     test_types_set1(bxor, 1);
426     test_types_set1(bxor, 2);
427     test_types_set1(bxor, 3);
428
429     test_types_set3(bor, 1);
430     test_types_set3(band, 1);
431     test_types_set3(band, 2);
432
433     test_types_set3(bxor, 1);
434     test_types_set3(bxor, 2);
435     test_types_set3(bxor, 3);
436
437     test_types_set4(sum, 1);
438     test_types_set4(prod, 1);
439
440     test_types_set5(lor, 1);
441     test_types_set5(lor, 2);
442     test_types_set5(lxor, 1);
443     test_types_set5(lxor, 2);
444     test_types_set5(lxor, 3);
445     test_types_set5(land, 1);
446     test_types_set5(land, 2);
447
448     maxloc_test(struct int_test, MPI_2INT);
449     maxloc_test(struct long_test, MPI_LONG_INT);
450     maxloc_test(struct short_test, MPI_SHORT_INT);
451     maxloc_test(struct float_test, MPI_FLOAT_INT);
452     maxloc_test(struct double_test, MPI_DOUBLE_INT);
453
454     minloc_test(struct int_test, MPI_2INT);
455     minloc_test(struct long_test, MPI_LONG_INT);
456     minloc_test(struct short_test, MPI_SHORT_INT);
457     minloc_test(struct float_test, MPI_FLOAT_INT);
458     minloc_test(struct double_test, MPI_DOUBLE_INT);
459
460     MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_ARE_FATAL);
461     MTest_Finalize(cerrcnt);
462     MPI_Finalize();
463     return 0;
464 }