Logo AND Algorithmique Numérique Distribuée

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