1 /* -*- Mode: c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
3 * (C) 2012 by Argonne National Laboratory.
4 * See COPYRIGHT in top-level directory.
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. */
16 #define equals(a, b) ((long long)(a) == (long long)(b))
18 /* assert-like macro that bumps the err count and emits a message */
24 fprintf(stderr, "check failed: (%s), line %d\n", #x_, __LINE__); \
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); \
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)
43 int main(int argc, char *argv[])
47 int size, elements, count;
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;
57 MPI_Init(&argc, &argv);
58 MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
59 MPI_Comm_size(MPI_COMM_WORLD, &wsize);
61 check(sizeof(MPI_Count) >= sizeof(int));
62 check(sizeof(MPI_Count) >= sizeof(MPI_Aint));
63 check(sizeof(MPI_Count) >= sizeof(MPI_Offset));
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));
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))
76 /* a very large type */
77 MPI_Type_contiguous(INT_MAX, MPI_CHAR, &imax_contig);
78 MPI_Type_commit(&imax_contig);
80 /* a small-ish contig */
81 MPI_Type_contiguous(4, MPI_INT, &four_ints);
82 MPI_Type_commit(&four_ints);
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);
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);
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);
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 */
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 */
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));
130 check(equals(extent, imx4i_true_extent));
132 MPI_Type_get_extent(imx4i_rsz, &lb, &extent);
133 check(equals(lb, INT_MAX));
134 check(equals(extent, -1024));
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));
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));
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));
168 check(equals(extent, imx4i_true_extent));
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));
185 /* MPI_{Status_set_elements,Get_elements}{,_x} */
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));
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));
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
209 #define check_set_elements(type_, elts_) \
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)); \
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)); \
232 check(equals(elements, (elts_))); \
234 check(equals(elements_x, (elts_))); \
235 check(equals(count, 1)); \
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));
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);
249 MPI_Reduce((wrank == 0 ? MPI_IN_PLACE : &errs), &errs, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
252 printf("found %d errors\n", errs);
255 printf(" No errors\n");