1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
4 * (C) 2014 by Argonne National Laboratory.
5 * See COPYRIGHT in top-level directory.
8 #include "mpitestconf.h"
11 #if defined(HAVE_STDIO_H) || defined(STDC_HEADERS)
14 #if defined(HAVE_STDLIB_H) || defined(STDC_HEADERS)
17 #if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
24 /* This file contains code to generate a variety of MPI datatypes for testing
25 the various MPI routines.
27 To simplify the test code, this generates an array of datatypes, buffers with
28 data and buffers with no data (0 bits) for use in send and receive
29 routines of various types.
31 In addition, this doesn't even test all of the possibilities. For example,
32 there is currently no test of sending more than one item defined with
35 Note also that this test assumes that the sending and receive types are
36 the same. MPI requires only that the type signatures match, which is
39 This code was drawn from the MPICH-1 test suite and modified to fit the
40 new MPICH test suite. It provides an alternative set of datatype tests
41 to the ones in mtest.c.
45 /* Change this to test only the basic, predefined types */
46 static int basic_only = 0;
49 Arrays types, inbufs, outbufs, and counts are allocated by the
50 CALLER. n on input is the maximum number; on output, it is the
53 See MTestDatatype2Allocate below for a routine to allocate these arrays.
55 We may want to add a routine to call to check that the proper data
62 Add a predefined MPI type to the tests. _count instances of the
65 #define SETUPBASICTYPE(_mpitype,_ctype,_count) { \
67 if (cnt > *n) {*n = cnt; return; } \
68 types[cnt] = _mpitype; \
69 inbufs[cnt] = (void *)calloc(_count,sizeof(_ctype)); \
70 outbufs[cnt] = (void *)malloc(sizeof(_ctype) * (_count)); \
71 a = (_ctype *)inbufs[cnt]; for (i=0; i<(_count); i++) a[i] = i; \
72 a = (_ctype *)outbufs[cnt]; for (i=0; i<(_count); i++) a[i] = 0; \
73 counts[cnt] = _count; bytesize[cnt] = sizeof(_ctype) * (_count); cnt++; }
76 Add a contiguous version of a predefined type. Send one instance of
77 the type which contains _count copies of the predefined type.
79 #define SETUPCONTIGTYPE(_mpitype,_ctype,_count) { \
80 int i; _ctype *a; char*myname; \
81 char _basename[MPI_MAX_OBJECT_NAME]; int _basenamelen;\
82 if (cnt > *n) {*n = cnt; return; }\
83 MPI_Type_contiguous(_count, _mpitype, types + cnt);\
84 MPI_Type_commit(types + cnt);\
85 inbufs[cnt] = (void *)calloc(_count, sizeof(_ctype)); \
86 outbufs[cnt] = (void *)malloc(sizeof(_ctype) * (_count)); \
87 a = (_ctype *)inbufs[cnt]; for (i=0; i<(_count); i++) a[i] = i; \
88 a = (_ctype *)outbufs[cnt]; for (i=0; i<(_count); i++) a[i] = 0; \
89 myname = (char *)malloc(STR_SIZE);\
90 MPI_Type_get_name(_mpitype, _basename, &_basenamelen); \
91 snprintf(myname, STR_SIZE, "Contig type %s", _basename); \
92 MPI_Type_set_name(types[cnt], myname); \
94 counts[cnt] = 1; bytesize[cnt] = sizeof(_ctype) * (_count); cnt++; }
97 Create a vector with _count elements, separated by stride _stride,
98 of _mpitype. Each block has a single element.
100 #define SETUPVECTORTYPE(_mpitype,_ctype,_count,_stride,_name) { \
101 int i; _ctype *a; char *myname; \
102 char _basename[MPI_MAX_OBJECT_NAME]; int _basenamelen;\
103 if (cnt > *n) {*n = cnt; return; }\
104 MPI_Type_vector(_count, 1, _stride, _mpitype, types + cnt); \
105 MPI_Type_commit(types + cnt);\
106 inbufs[cnt] = (void *)calloc(sizeof(_ctype) * (_count) * (_stride),1); \
107 outbufs[cnt] = (void *)calloc(sizeof(_ctype) * (_count) * (_stride),1); \
108 a = (_ctype *)inbufs[cnt]; for (i=0; i<(_count); i++) a[i*(_stride)] = i; \
109 a = (_ctype *)outbufs[cnt]; for (i=0; i<(_count); i++) a[i*(_stride)] = 0; \
110 myname = (char *)malloc(STR_SIZE);\
111 MPI_Type_get_name(_mpitype, _basename, &_basenamelen); \
112 snprintf(myname, STR_SIZE, "Vector type %s", _basename); \
113 MPI_Type_set_name(types[cnt], myname); \
115 counts[cnt] = 1; bytesize[cnt] = sizeof(_ctype) * (_count) * (_stride) ;\
118 /* This indexed type is setup like a contiguous type .
119 Note that systems may try to convert this to contiguous, so we'll
120 eventually need a test that has holes in it */
121 #define SETUPINDEXTYPE(_mpitype,_ctype,_count,_name) { \
122 int i; int *lens, *disp; _ctype *a; char *myname; \
123 char _basename[MPI_MAX_OBJECT_NAME]; int _basenamelen;\
124 if (cnt > *n) {*n = cnt; return; }\
125 lens = (int *)malloc((_count) * sizeof(int)); \
126 disp = (int *)malloc((_count) * sizeof(int)); \
127 for (i=0; i<(_count); i++) { lens[i] = 1; disp[i] = i; } \
128 MPI_Type_indexed((_count), lens, disp, _mpitype, types + cnt);\
129 free(lens); free(disp); \
130 MPI_Type_commit(types + cnt);\
131 inbufs[cnt] = (void *)calloc((_count), sizeof(_ctype)); \
132 outbufs[cnt] = (void *)malloc(sizeof(_ctype) * (_count)); \
133 a = (_ctype *)inbufs[cnt]; for (i=0; i<(_count); i++) a[i] = i; \
134 a = (_ctype *)outbufs[cnt]; for (i=0; i<(_count); i++) a[i] = 0; \
135 myname = (char *)malloc(STR_SIZE);\
136 MPI_Type_get_name(_mpitype, _basename, &_basenamelen); \
137 snprintf(myname, STR_SIZE, "Index type %s", _basename); \
138 MPI_Type_set_name(types[cnt], myname); \
140 counts[cnt] = 1; bytesize[cnt] = sizeof(_ctype) * (_count); cnt++; }
142 /* This defines a structure of two basic members; by chosing things like
143 (char, double), various packing and alignment tests can be made */
144 #define SETUPSTRUCT2TYPE(_mpitype1,_ctype1,_mpitype2,_ctype2,_count,_tname) { \
145 int i; char *myname; \
146 MPI_Datatype b[3]; int cnts[3]; \
147 struct name { _ctype1 a1; _ctype2 a2; } *a, samp; \
149 if (cnt > *n) {*n = cnt; return; } \
150 b[0] = _mpitype1; b[1] = _mpitype2; b[2] = MPI_UB; \
151 cnts[0] = 1; cnts[1] = 1; cnts[2] = 1; \
152 MPI_Get_address(&(samp.a2), &disp[1]); \
153 MPI_Get_address(&(samp.a1), &disp[0]); \
154 MPI_Get_address(&(samp) + 1, &disp[2]); \
155 disp[1] = disp[1] - disp[0]; disp[2] = disp[2] - disp[0]; disp[0] = 0; \
156 MPI_Type_create_struct(3, cnts, disp, b, types + cnt); \
157 MPI_Type_commit(types + cnt); \
158 inbufs[cnt] = (void *)calloc(sizeof(struct name) * (_count),1); \
159 outbufs[cnt] = (void *)calloc(sizeof(struct name) * (_count),1); \
160 a = (struct name *)inbufs[cnt]; for (i=0; i<(_count); i++) { a[i].a1 = i; \
162 a = (struct name *)outbufs[cnt]; for (i=0; i<(_count); i++) { a[i].a1 = 0; \
164 myname = (char *)malloc(STR_SIZE); \
165 snprintf(myname, STR_SIZE, "Struct type %s", _tname); \
166 MPI_Type_set_name(types[cnt], myname); \
168 counts[cnt] = (_count); bytesize[cnt] = sizeof(struct name) * (_count);cnt++; }
170 /* This accomplished the same effect as VECTOR, but allow a count of > 1 */
171 #define SETUPSTRUCTTYPEUB(_mpitype,_ctype,_count,_stride) { \
172 int i; _ctype *a; char *myname; \
173 int blens[2]; MPI_Aint disps[2]; MPI_Datatype mtypes[2]; \
174 char _basename[MPI_MAX_OBJECT_NAME]; int _basenamelen;\
175 if (cnt > *n) {*n = cnt; return; } \
176 blens[0] = 1; blens[1] = 1; disps[0] = 0; \
177 disps[1] = (_stride) * sizeof(_ctype); \
178 mtypes[0] = _mpitype; mtypes[1] = MPI_UB; \
179 MPI_Type_create_struct(2, blens, disps, mtypes, types + cnt); \
180 MPI_Type_commit(types + cnt); \
181 inbufs[cnt] = (void *)calloc(sizeof(_ctype) * (_count) * (_stride),1);\
182 outbufs[cnt] = (void *)calloc(sizeof(_ctype) * (_count) * (_stride),1);\
183 a = (_ctype *)inbufs[cnt]; for (i=0; i<(_count); i++) a[i*(_stride)] = i; \
184 a = (_ctype *)outbufs[cnt]; for (i=0; i<(_count); i++) a[i*(_stride)] = 0; \
185 myname = (char *)malloc(STR_SIZE); \
186 MPI_Type_get_name(_mpitype, _basename, &_basenamelen); \
187 snprintf(myname, STR_SIZE, "Struct (MPI_UB) type %s", _basename); \
188 MPI_Type_set_name(types[cnt], myname); \
190 counts[cnt] = (_count); \
191 bytesize[cnt] = sizeof(_ctype) * (_count) * (_stride);\
195 * Set whether only the basic types should be generated
197 void MTestDatatype2BasicOnly(void)
202 static int nbasic_types = 0;
203 /* On input, n is the size of the various buffers. On output,
204 it is the number available types
206 void MTestDatatype2Generate(MPI_Datatype * types, void **inbufs, void **outbufs,
207 int *counts, int *bytesize, int *n)
209 int cnt = 0; /* Number of defined types */
210 int typecnt = 10; /* Number of instances to send in most cases */
211 int stride = 9; /* Number of elements in vector to stride */
213 /* First, generate an element of each basic type */
214 SETUPBASICTYPE(MPI_CHAR, char, typecnt);
215 SETUPBASICTYPE(MPI_SHORT, short, typecnt);
216 SETUPBASICTYPE(MPI_INT, int, typecnt);
217 SETUPBASICTYPE(MPI_LONG, long, typecnt);
218 SETUPBASICTYPE(MPI_UNSIGNED_CHAR, unsigned char, typecnt);
219 SETUPBASICTYPE(MPI_UNSIGNED_SHORT, unsigned short, typecnt);
220 SETUPBASICTYPE(MPI_UNSIGNED, unsigned, typecnt);
221 SETUPBASICTYPE(MPI_UNSIGNED_LONG, unsigned long, typecnt);
222 SETUPBASICTYPE(MPI_FLOAT, float, typecnt);
223 SETUPBASICTYPE(MPI_DOUBLE, double, typecnt);
224 SETUPBASICTYPE(MPI_BYTE, char, typecnt);
225 #ifdef HAVE_LONG_LONG_INT
226 SETUPBASICTYPE(MPI_LONG_LONG_INT, long long, typecnt);
228 #ifdef HAVE_LONG_DOUBLE
229 SETUPBASICTYPE(MPI_LONG_DOUBLE, long double, typecnt);
237 /* Generate contiguous data items */
238 SETUPCONTIGTYPE(MPI_CHAR, char, typecnt);
239 SETUPCONTIGTYPE(MPI_SHORT, short, typecnt);
240 SETUPCONTIGTYPE(MPI_INT, int, typecnt);
241 SETUPCONTIGTYPE(MPI_LONG, long, typecnt);
242 SETUPCONTIGTYPE(MPI_UNSIGNED_CHAR, unsigned char, typecnt);
243 SETUPCONTIGTYPE(MPI_UNSIGNED_SHORT, unsigned short, typecnt);
244 SETUPCONTIGTYPE(MPI_UNSIGNED, unsigned, typecnt);
245 SETUPCONTIGTYPE(MPI_UNSIGNED_LONG, unsigned long, typecnt);
246 SETUPCONTIGTYPE(MPI_FLOAT, float, typecnt);
247 SETUPCONTIGTYPE(MPI_DOUBLE, double, typecnt);
248 SETUPCONTIGTYPE(MPI_BYTE, char, typecnt);
249 #ifdef HAVE_LONG_LONG_INT
250 SETUPCONTIGTYPE(MPI_LONG_LONG_INT, long long, typecnt);
252 #ifdef HAVE_LONG_DOUBLE
253 SETUPCONTIGTYPE(MPI_LONG_DOUBLE, long double, typecnt);
256 /* Generate vector items */
257 SETUPVECTORTYPE(MPI_CHAR, char, typecnt, stride, "MPI_CHAR");
258 SETUPVECTORTYPE(MPI_SHORT, short, typecnt, stride, "MPI_SHORT");
259 SETUPVECTORTYPE(MPI_INT, int, typecnt, stride, "MPI_INT");
260 SETUPVECTORTYPE(MPI_LONG, long, typecnt, stride, "MPI_LONG");
261 SETUPVECTORTYPE(MPI_UNSIGNED_CHAR, unsigned char, typecnt, stride, "MPI_UNSIGNED_CHAR");
262 SETUPVECTORTYPE(MPI_UNSIGNED_SHORT, unsigned short, typecnt, stride, "MPI_UNSIGNED_SHORT");
263 SETUPVECTORTYPE(MPI_UNSIGNED, unsigned, typecnt, stride, "MPI_UNSIGNED");
264 SETUPVECTORTYPE(MPI_UNSIGNED_LONG, unsigned long, typecnt, stride, "MPI_UNSIGNED_LONG");
265 SETUPVECTORTYPE(MPI_FLOAT, float, typecnt, stride, "MPI_FLOAT");
266 SETUPVECTORTYPE(MPI_DOUBLE, double, typecnt, stride, "MPI_DOUBLE");
267 SETUPVECTORTYPE(MPI_BYTE, char, typecnt, stride, "MPI_BYTE");
268 #ifdef HAVE_LONG_LONG_INT
269 SETUPVECTORTYPE(MPI_LONG_LONG_INT, long long, typecnt, stride, "MPI_LONG_LONG_INT");
271 #ifdef HAVE_LONG_DOUBLE
272 SETUPVECTORTYPE(MPI_LONG_DOUBLE, long double, typecnt, stride, "MPI_LONG_DOUBLE");
275 /* Generate indexed items */
276 SETUPINDEXTYPE(MPI_CHAR, char, typecnt, "MPI_CHAR");
277 SETUPINDEXTYPE(MPI_SHORT, short, typecnt, "MPI_SHORT");
278 SETUPINDEXTYPE(MPI_INT, int, typecnt, "MPI_INT");
279 SETUPINDEXTYPE(MPI_LONG, long, typecnt, "MPI_LONG");
280 SETUPINDEXTYPE(MPI_UNSIGNED_CHAR, unsigned char, typecnt, "MPI_UNSIGNED_CHAR");
281 SETUPINDEXTYPE(MPI_UNSIGNED_SHORT, unsigned short, typecnt, "MPI_UNSIGNED_SHORT");
282 SETUPINDEXTYPE(MPI_UNSIGNED, unsigned, typecnt, "MPI_UNSIGNED");
283 SETUPINDEXTYPE(MPI_UNSIGNED_LONG, unsigned long, typecnt, "MPI_UNSIGNED_LONG");
284 SETUPINDEXTYPE(MPI_FLOAT, float, typecnt, "MPI_FLOAT");
285 SETUPINDEXTYPE(MPI_DOUBLE, double, typecnt, "MPI_DOUBLE");
286 SETUPINDEXTYPE(MPI_BYTE, char, typecnt, "MPI_BYTE");
287 #ifdef HAVE_LONG_LONG_INT
288 SETUPINDEXTYPE(MPI_LONG_LONG_INT, long long, typecnt, "MPI_LONG_LONG_INT");
290 #ifdef HAVE_LONG_DOUBLE
291 SETUPINDEXTYPE(MPI_LONG_DOUBLE, long double, typecnt, "MPI_LONG_DOUBLE");
294 /* Generate struct items */
295 SETUPSTRUCT2TYPE(MPI_CHAR, char, MPI_DOUBLE, double, typecnt, "char-double");
296 SETUPSTRUCT2TYPE(MPI_DOUBLE, double, MPI_CHAR, char, typecnt, "double-char");
297 SETUPSTRUCT2TYPE(MPI_UNSIGNED, unsigned, MPI_DOUBLE, double, typecnt, "unsigned-double");
298 SETUPSTRUCT2TYPE(MPI_FLOAT, float, MPI_LONG, long, typecnt, "float-long");
299 SETUPSTRUCT2TYPE(MPI_UNSIGNED_CHAR, unsigned char, MPI_CHAR, char, typecnt,
300 "unsigned char-char");
301 SETUPSTRUCT2TYPE(MPI_UNSIGNED_SHORT, unsigned short, MPI_DOUBLE, double,
302 typecnt, "unsigned short-double");
304 /* Generate struct using MPI_UB */
305 SETUPSTRUCTTYPEUB(MPI_CHAR, char, typecnt, stride);
306 SETUPSTRUCTTYPEUB(MPI_SHORT, short, typecnt, stride);
307 SETUPSTRUCTTYPEUB(MPI_INT, int, typecnt, stride);
308 SETUPSTRUCTTYPEUB(MPI_LONG, long, typecnt, stride);
309 SETUPSTRUCTTYPEUB(MPI_UNSIGNED_CHAR, unsigned char, typecnt, stride);
310 SETUPSTRUCTTYPEUB(MPI_UNSIGNED_SHORT, unsigned short, typecnt, stride);
311 SETUPSTRUCTTYPEUB(MPI_UNSIGNED, unsigned, typecnt, stride);
312 SETUPSTRUCTTYPEUB(MPI_UNSIGNED_LONG, unsigned long, typecnt, stride);
313 SETUPSTRUCTTYPEUB(MPI_FLOAT, float, typecnt, stride);
314 SETUPSTRUCTTYPEUB(MPI_DOUBLE, double, typecnt, stride);
315 SETUPSTRUCTTYPEUB(MPI_BYTE, char, typecnt, stride);
317 /* 60 different entries to this point + 4 for long long and
318 * 4 for long double */
323 MAX_TEST should be 1 + actual max (allows us to check that it was,
324 indeed, large enough)
327 void MTestDatatype2Allocate(MPI_Datatype ** types, void ***inbufs,
328 void ***outbufs, int **counts, int **bytesize, int *n)
330 *types = (MPI_Datatype *) malloc(MAX_TEST * sizeof(MPI_Datatype));
331 *inbufs = (void **) malloc(MAX_TEST * sizeof(void *));
332 *outbufs = (void **) malloc(MAX_TEST * sizeof(void *));
333 *counts = (int *) malloc(MAX_TEST * sizeof(int));
334 *bytesize = (int *) malloc(MAX_TEST * sizeof(int));
338 int MTestDatatype2Check(void *inbuf, void *outbuf, int size_bytes)
340 char *in = (char *) inbuf, *out = (char *) outbuf;
342 for (i = 0; i < size_bytes; i++) {
343 if (in[i] != out[i]) {
351 * This is a version of CheckData that prints error messages
353 static int MtestDatatype2CheckAndPrint(void *inbuf, void *outbuf, int size_bytes,
354 char *typename, int typenum)
356 int errloc, world_rank;
358 if ((errloc = MTestDatatype2Check(inbuf, outbuf, size_bytes))) {
360 MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
362 "Error in data with type %s (type %d on %d) at byte %d of %d\n",
363 typename, typenum, world_rank, errloc - 1, size_bytes);
365 p2 = (char *) outbuf;
366 fprintf(stderr, "Got %hhx expected %hhx\n", p2[errloc - 1], p1[errloc - 1]);
371 void MTestDatatype2Free(MPI_Datatype * types, void **inbufs, void **outbufs,
372 int *counts, int *bytesize, int n)
375 for (i = 0; i < n; i++) {
380 /* Only if not basic ... */
381 if (i >= nbasic_types)
382 MPI_Type_free(types + i);