Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
31f6a2d4192b1df9ff12898d79e6df4173d6bf8b
[simgrid.git] / teshsuite / smpi / mpich3-test / datatype / large-count.c
1 /* -*- Mode: c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  *  (C) 2012 by Argonne National Laboratory.
4  *      See COPYRIGHT in top-level directory.
5  */
6
7 /* This test checks for large count functionality ("MPI_Count") mandated by
8  * MPI-3, as well as behavior of corresponding pre-MPI-3 interfaces that now
9  * have better defined behavior when an "int" quantity would overflow. */
10
11 #include <limits.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <mpi.h>
15
16 /* assert-like macro that bumps the err count and emits a message */
17 #define check(x_)                                                                 \
18     do {                                                                          \
19         if (!(x_)) {                                                              \
20             ++errs;                                                               \
21             if (errs < 10) {                                                      \
22                 fprintf(stderr, "check failed: (%s), line %d\n", #x_, __LINE__); \
23             }                                                                     \
24         }                                                                         \
25     } while (0)
26
27 /* Abort when using unimplemented functions.  Currently, it should not happen,
28  * since sizeof(MPI_Count) == sizeof(int), but it avoids compile errors about
29  * undefined functions. */
30 #define err_unimpl(func) do {                                 \
31     fprintf(stderr, "ERROR: %s is not implemented\n", #func); \
32     abort();                                                  \
33   } while (0)
34
35 #define MPI_Type_size_x(a,b)              err_unimpl(MPI_Type_size_x)
36 #define MPI_Type_get_extent_x(a,b,c)      err_unimpl(MPI_Type_get_extent_x)
37 #define MPI_Type_get_true_extent_x(a,b,c) err_unimpl(MPI_Type_get_true_extent_x)
38 #define MPI_Get_elements_x(a,b,c)         err_unimpl(MPI_Get_elements_x)
39 #define MPI_Status_set_elements_x(a,b,c)  err_unimpl(MPI_Status_set_elements_x)
40
41 int main(int argc, char *argv[])
42 {
43     int errs = 0;
44     int wrank, wsize;
45     int size, elements, count;
46     MPI_Aint lb, extent;
47     MPI_Count size_x, lb_x, extent_x, elements_x;
48     double imx4i_true_extent;
49     MPI_Datatype imax_contig = MPI_DATATYPE_NULL;
50     MPI_Datatype four_ints = MPI_DATATYPE_NULL;
51     MPI_Datatype imx4i = MPI_DATATYPE_NULL;
52     MPI_Datatype imx4i_rsz = MPI_DATATYPE_NULL;
53     MPI_Status status;
54
55     MPI_Init(&argc, &argv);
56     MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
57     MPI_Comm_size(MPI_COMM_WORLD, &wsize);
58
59     check(sizeof(MPI_Count) >= sizeof(int));
60     check(sizeof(MPI_Count) >= sizeof(MPI_Aint));
61     check(sizeof(MPI_Count) >= sizeof(MPI_Offset));
62
63     /* the following two checks aren't explicitly required by the standard, but
64      * it's hard to imagine a world without them holding true and so most of the
65      * subsequent code probably depends on them to some degree */
66     check(sizeof(MPI_Aint) >= sizeof(int));
67     check(sizeof(MPI_Offset) >= sizeof(int));
68
69     /* not much point in checking for integer overflow cases if MPI_Count is
70      * only as large as an int */
71     if (sizeof(MPI_Count) == sizeof(int))
72         goto epilogue;
73
74     /* a very large type */
75     MPI_Type_contiguous(INT_MAX, MPI_CHAR, &imax_contig);
76     MPI_Type_commit(&imax_contig);
77
78     /* a small-ish contig */
79     MPI_Type_contiguous(4, MPI_INT, &four_ints);
80     MPI_Type_commit(&four_ints);
81
82     /* a type with size>INT_MAX */
83     MPI_Type_vector(INT_MAX/2, 1, 3, four_ints, &imx4i);
84     MPI_Type_commit(&imx4i);
85     /* don't forget, ub for dtype w/ stride doesn't include any holes at the end
86      * of the type, hence the more complicated calculation below */
87     imx4i_true_extent = 3LL*4LL*sizeof(int)*((INT_MAX/2)-1) + 4LL*sizeof(int);
88
89     /* sanity check that the MPI_COUNT predefined named datatype exists */
90     MPI_Send(&imx4i_true_extent, 1, MPI_COUNT, MPI_PROC_NULL, 0, MPI_COMM_SELF);
91
92     /* the same oversized type but with goofy extents */
93     MPI_Type_create_resized(imx4i, /*lb=*/INT_MAX, /*extent=*/-1024, &imx4i_rsz);
94     MPI_Type_commit(&imx4i_rsz);
95
96     /* MPI_Type_size */
97     MPI_Type_size(imax_contig, &size);
98     check(size == INT_MAX);
99     MPI_Type_size(four_ints, &size);
100     check(size == 4*sizeof(int));
101     MPI_Type_size(imx4i, &size);
102     check(size == MPI_UNDEFINED); /* should overflow an int */
103     MPI_Type_size(imx4i_rsz, &size);
104     check(size == MPI_UNDEFINED); /* should overflow an int */
105
106     /* MPI_Type_size_x */
107     MPI_Type_size_x(imax_contig, &size_x);
108     check(size_x == INT_MAX);
109     MPI_Type_size_x(four_ints, &size_x);
110     check(size_x == 4*sizeof(int));
111     MPI_Type_size_x(imx4i, &size_x);
112     check(size_x == 4LL*sizeof(int)*(INT_MAX/2)); /* should overflow an int */
113     MPI_Type_size_x(imx4i_rsz, &size_x);
114     check(size_x == 4LL*sizeof(int)*(INT_MAX/2)); /* should overflow an int */
115
116     /* MPI_Type_get_extent */
117     MPI_Type_get_extent(imax_contig, &lb, &extent);
118     check(lb == 0);
119     check(extent == INT_MAX);
120     MPI_Type_get_extent(four_ints, &lb, &extent);
121     check(lb == 0);
122     check(extent == 4*sizeof(int));
123     MPI_Type_get_extent(imx4i, &lb, &extent);
124     check(lb == 0);
125     if (sizeof(MPI_Aint) == sizeof(int))
126         check(extent == MPI_UNDEFINED);
127     else
128         check(extent == imx4i_true_extent);
129
130     MPI_Type_get_extent(imx4i_rsz, &lb, &extent);
131     check(lb == INT_MAX);
132     check(extent == -1024);
133
134     /* MPI_Type_get_extent_x */
135     MPI_Type_get_extent_x(imax_contig, &lb_x, &extent_x);
136     check(lb_x == 0);
137     check(extent_x == INT_MAX);
138     MPI_Type_get_extent_x(four_ints, &lb_x, &extent_x);
139     check(lb_x == 0);
140     check(extent_x == 4*sizeof(int));
141     MPI_Type_get_extent_x(imx4i, &lb_x, &extent_x);
142     check(lb_x == 0);
143     check(extent_x == imx4i_true_extent);
144     MPI_Type_get_extent_x(imx4i_rsz, &lb_x, &extent_x);
145     check(lb_x == INT_MAX);
146     check(extent_x == -1024);
147
148     /* MPI_Type_get_true_extent */
149     MPI_Type_get_true_extent(imax_contig, &lb, &extent);
150     check(lb == 0);
151     check(extent == INT_MAX);
152     MPI_Type_get_true_extent(four_ints, &lb, &extent);
153     check(lb == 0);
154     check(extent == 4*sizeof(int));
155     MPI_Type_get_true_extent(imx4i, &lb, &extent);
156     check(lb == 0);
157     if (sizeof(MPI_Aint) == sizeof(int))
158         check(extent == MPI_UNDEFINED);
159     else
160         check(extent == imx4i_true_extent);
161     MPI_Type_get_true_extent(imx4i_rsz, &lb, &extent);
162     check(lb == 0);
163     if (sizeof(MPI_Aint) == sizeof(int))
164         check(extent == MPI_UNDEFINED);
165     else
166         check(extent == imx4i_true_extent);
167
168     /* MPI_Type_get_true_extent_x */
169     MPI_Type_get_true_extent_x(imax_contig, &lb_x, &extent_x);
170     check(lb_x == 0);
171     check(extent_x == INT_MAX);
172     MPI_Type_get_true_extent_x(four_ints, &lb_x, &extent_x);
173     check(lb_x == 0);
174     check(extent_x == 4*sizeof(int));
175     MPI_Type_get_true_extent_x(imx4i, &lb_x, &extent_x);
176     check(lb_x == 0);
177     check(extent_x == imx4i_true_extent);
178     MPI_Type_get_true_extent_x(imx4i_rsz, &lb_x, &extent_x);
179     check(lb_x == 0);
180     check(extent_x == imx4i_true_extent);
181
182
183     /* MPI_{Status_set_elements,Get_elements}{,_x} */
184
185     /* set simple */
186     MPI_Status_set_elements(&status, MPI_INT, 10);
187     MPI_Get_elements(&status, MPI_INT, &elements);
188     MPI_Get_elements_x(&status, MPI_INT, &elements_x);
189     MPI_Get_count(&status, MPI_INT, &count);
190     check(elements == 10);
191     check(elements_x == 10);
192     check(count == 10);
193
194     /* set_x simple */
195     MPI_Status_set_elements_x(&status, MPI_INT, 10);
196     MPI_Get_elements(&status, MPI_INT, &elements);
197     MPI_Get_elements_x(&status, MPI_INT, &elements_x);
198     MPI_Get_count(&status, MPI_INT, &count);
199     check(elements == 10);
200     check(elements_x == 10);
201     check(count == 10);
202
203     /* Sets elements corresponding to count=1 of the given MPI datatype, using
204      * set_elements and set_elements_x.  Checks expected values are returned by
205      * get_elements, get_elements_x, and get_count (including MPI_UNDEFINED
206      * clipping) */
207 #define check_set_elements(type_, elts_)                          \
208     do {                                                          \
209         elements = elements_x = count = 0xfeedface;               \
210         /* can't use legacy "set" for large element counts */     \
211         if ((elts_) <= INT_MAX) {                                 \
212             MPI_Status_set_elements(&status, (type_), 1);         \
213             MPI_Get_elements(&status, (type_), &elements);        \
214             MPI_Get_elements_x(&status, (type_), &elements_x);    \
215             MPI_Get_count(&status, (type_), &count);              \
216             check(elements == (elts_));                           \
217             check(elements_x == (elts_));                         \
218             check(count == 1);                                    \
219         }                                                         \
220                                                                   \
221         elements = elements_x = count = 0xfeedface;               \
222         MPI_Status_set_elements_x(&status, (type_), 1);           \
223         MPI_Get_elements(&status, (type_), &elements);            \
224         MPI_Get_elements_x(&status, (type_), &elements_x);        \
225         MPI_Get_count(&status, (type_), &count);                  \
226         if ((elts_) > INT_MAX) {                                  \
227             check(elements == MPI_UNDEFINED);                     \
228         }                                                         \
229         else {                                                    \
230             check(elements == (elts_));                           \
231         }                                                         \
232         check(elements_x == (elts_));                             \
233         check(count == 1);                                        \
234     } while (0)                                                   \
235
236     check_set_elements(imax_contig, INT_MAX);
237     check_set_elements(four_ints, 4);
238     check_set_elements(imx4i, 4LL*(INT_MAX/2));
239     check_set_elements(imx4i_rsz, 4LL*(INT_MAX/2));
240
241 epilogue:
242     if (imax_contig != MPI_DATATYPE_NULL) MPI_Type_free(&imax_contig);
243     if (four_ints != MPI_DATATYPE_NULL) MPI_Type_free(&four_ints);
244     if (imx4i != MPI_DATATYPE_NULL) MPI_Type_free(&imx4i);
245     if (imx4i_rsz != MPI_DATATYPE_NULL) MPI_Type_free(&imx4i_rsz);
246
247     MPI_Reduce((wrank == 0 ? MPI_IN_PLACE : &errs), &errs, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
248     if (wrank == 0) {
249         if (errs) {
250             printf("found %d errors\n", errs);
251         }
252         else {
253             printf(" No errors\n");
254         }
255     }
256
257     MPI_Finalize();
258
259     return 0;
260 }