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
60 Add a predefined MPI type to the tests. _count instances of the
63 #define SETUPBASICTYPE(_mpitype,_ctype,_count) { \
65 if (cnt > *n) {*n = cnt; return; } \
66 types[cnt] = _mpitype; \
67 inbufs[cnt] = (void *)calloc(_count,sizeof(_ctype)); \
68 outbufs[cnt] = (void *)malloc(sizeof(_ctype) * (_count)); \
69 a = (_ctype *)inbufs[cnt]; for (i=0; i<(_count); i++) a[i] = i; \
70 a = (_ctype *)outbufs[cnt]; for (i=0; i<(_count); i++) a[i] = 0; \
71 counts[cnt] = _count; bytesize[cnt] = sizeof(_ctype) * (_count); cnt++; }
74 Add a contiguous version of a predefined type. Send one instance of
75 the type which contains _count copies of the predefined type.
77 #define SETUPCONTIGTYPE(_mpitype,_ctype,_count) { \
78 int i; _ctype *a; char*myname; \
79 char _basename[MPI_MAX_OBJECT_NAME]; int _basenamelen;\
80 if (cnt > *n) {*n = cnt; return; }\
81 MPI_Type_contiguous(_count, _mpitype, types + cnt);\
82 MPI_Type_commit(types + cnt);\
83 inbufs[cnt] = (void *)calloc(_count, sizeof(_ctype)); \
84 outbufs[cnt] = (void *)malloc(sizeof(_ctype) * (_count)); \
85 a = (_ctype *)inbufs[cnt]; for (i=0; i<(_count); i++) a[i] = i; \
86 a = (_ctype *)outbufs[cnt]; for (i=0; i<(_count); i++) a[i] = 0; \
87 myname = (char *)malloc(100);\
88 MPI_Type_get_name(_mpitype, _basename, &_basenamelen); \
89 snprintf(myname, 100, "Contig type %s", _basename); \
90 MPI_Type_set_name(types[cnt], myname); \
92 counts[cnt] = 1; bytesize[cnt] = sizeof(_ctype) * (_count); cnt++; }
95 Create a vector with _count elements, separated by stride _stride,
96 of _mpitype. Each block has a single element.
98 #define SETUPVECTORTYPE(_mpitype,_ctype,_count,_stride,_name) { \
99 int i; _ctype *a; char *myname; \
100 char _basename[MPI_MAX_OBJECT_NAME]; int _basenamelen;\
101 if (cnt > *n) {*n = cnt; return; }\
102 MPI_Type_vector(_count, 1, _stride, _mpitype, types + cnt); \
103 MPI_Type_commit(types + cnt);\
104 inbufs[cnt] = (void *)calloc(sizeof(_ctype) * (_count) * (_stride),1); \
105 outbufs[cnt] = (void *)calloc(sizeof(_ctype) * (_count) * (_stride),1); \
106 a = (_ctype *)inbufs[cnt]; for (i=0; i<(_count); i++) a[i*(_stride)] = i; \
107 a = (_ctype *)outbufs[cnt]; for (i=0; i<(_count); i++) a[i*(_stride)] = 0; \
108 myname = (char *)malloc(100);\
109 MPI_Type_get_name(_mpitype, _basename, &_basenamelen); \
110 snprintf(myname, 100, "Vector type %s", _basename); \
111 MPI_Type_set_name(types[cnt], myname); \
113 counts[cnt] = 1; bytesize[cnt] = sizeof(_ctype) * (_count) * (_stride) ;\
116 /* This indexed type is setup like a contiguous type .
117 Note that systems may try to convert this to contiguous, so we'll
118 eventually need a test that has holes in it */
119 #define SETUPINDEXTYPE(_mpitype,_ctype,_count,_name) { \
120 int i; int *lens, *disp; _ctype *a; char *myname; \
121 char _basename[MPI_MAX_OBJECT_NAME]; int _basenamelen;\
122 if (cnt > *n) {*n = cnt; return; }\
123 lens = (int *)malloc((_count) * sizeof(int)); \
124 disp = (int *)malloc((_count) * sizeof(int)); \
125 for (i=0; i<(_count); i++) { lens[i] = 1; disp[i] = i; } \
126 MPI_Type_indexed((_count), lens, disp, _mpitype, types + cnt);\
127 free(lens); free(disp); \
128 MPI_Type_commit(types + cnt);\
129 inbufs[cnt] = (void *)calloc((_count), sizeof(_ctype)); \
130 outbufs[cnt] = (void *)malloc(sizeof(_ctype) * (_count)); \
131 a = (_ctype *)inbufs[cnt]; for (i=0; i<(_count); i++) a[i] = i; \
132 a = (_ctype *)outbufs[cnt]; for (i=0; i<(_count); i++) a[i] = 0; \
133 myname = (char *)malloc(100);\
134 MPI_Type_get_name(_mpitype, _basename, &_basenamelen); \
135 snprintf(myname, 100, "Index type %s", _basename); \
136 MPI_Type_set_name(types[cnt], myname); \
138 counts[cnt] = 1; bytesize[cnt] = sizeof(_ctype) * (_count); cnt++; }
140 /* This defines a structure of two basic members; by chosing things like
141 (char, double), various packing and alignment tests can be made */
142 #define SETUPSTRUCT2TYPE(_mpitype1,_ctype1,_mpitype2,_ctype2,_count,_tname) { \
143 int i; char *myname; \
144 MPI_Datatype b[3]; int cnts[3]; \
145 struct name { _ctype1 a1; _ctype2 a2; } *a, samp; \
147 if (cnt > *n) {*n = cnt; return; } \
148 b[0] = _mpitype1; b[1] = _mpitype2; b[2] = MPI_UB; \
149 cnts[0] = 1; cnts[1] = 1; cnts[2] = 1; \
150 MPI_Get_address(&(samp.a2), &disp[1]); \
151 MPI_Get_address(&(samp.a1), &disp[0]); \
152 MPI_Get_address(&(samp) + 1, &disp[2]); \
153 disp[1] = disp[1] - disp[0]; disp[2] = disp[2] - disp[0]; disp[0] = 0; \
154 MPI_Type_create_struct(3, cnts, disp, b, types + cnt); \
155 MPI_Type_commit(types + cnt); \
156 inbufs[cnt] = (void *)calloc(sizeof(struct name) * (_count),1); \
157 outbufs[cnt] = (void *)calloc(sizeof(struct name) * (_count),1); \
158 a = (struct name *)inbufs[cnt]; for (i=0; i<(_count); i++) { a[i].a1 = i; \
160 a = (struct name *)outbufs[cnt]; for (i=0; i<(_count); i++) { a[i].a1 = 0; \
162 myname = (char *)malloc(100); \
163 snprintf(myname, 100, "Struct type %s", _tname); \
164 MPI_Type_set_name(types[cnt], myname); \
166 counts[cnt] = (_count); bytesize[cnt] = sizeof(struct name) * (_count);cnt++; }
168 /* This accomplished the same effect as VECTOR, but allow a count of > 1 */
169 #define SETUPSTRUCTTYPEUB(_mpitype,_ctype,_count,_stride) { \
170 int i; _ctype *a; char *myname; \
171 int blens[2]; MPI_Aint disps[2]; MPI_Datatype mtypes[2]; \
172 char _basename[MPI_MAX_OBJECT_NAME]; int _basenamelen;\
173 if (cnt > *n) {*n = cnt; return; } \
174 blens[0] = 1; blens[1] = 1; disps[0] = 0; \
175 disps[1] = (_stride) * sizeof(_ctype); \
176 mtypes[0] = _mpitype; mtypes[1] = MPI_UB; \
177 MPI_Type_create_struct(2, blens, disps, mtypes, types + cnt); \
178 MPI_Type_commit(types + cnt); \
179 inbufs[cnt] = (void *)calloc(sizeof(_ctype) * (_count) * (_stride),1);\
180 outbufs[cnt] = (void *)calloc(sizeof(_ctype) * (_count) * (_stride),1);\
181 a = (_ctype *)inbufs[cnt]; for (i=0; i<(_count); i++) a[i*(_stride)] = i; \
182 a = (_ctype *)outbufs[cnt]; for (i=0; i<(_count); i++) a[i*(_stride)] = 0; \
183 myname = (char *)malloc(100); \
184 MPI_Type_get_name(_mpitype, _basename, &_basenamelen); \
185 snprintf(myname, 100, "Struct (MPI_UB) type %s", _basename); \
186 MPI_Type_set_name(types[cnt], myname); \
188 counts[cnt] = (_count); \
189 bytesize[cnt] = sizeof(_ctype) * (_count) * (_stride);\
193 * Set whether only the basic types should be generated
195 void MTestDatatype2BasicOnly(void)
200 static int nbasic_types = 0;
201 /* On input, n is the size of the various buffers. On output,
202 it is the number available types
204 void MTestDatatype2Generate(MPI_Datatype * types, void **inbufs, void **outbufs,
205 int *counts, int *bytesize, int *n)
207 int cnt = 0; /* Number of defined types */
208 int typecnt = 10; /* Number of instances to send in most cases */
209 int stride = 9; /* Number of elements in vector to stride */
211 /* First, generate an element of each basic type */
212 SETUPBASICTYPE(MPI_CHAR, char, typecnt);
213 SETUPBASICTYPE(MPI_SHORT, short, typecnt);
214 SETUPBASICTYPE(MPI_INT, int, typecnt);
215 SETUPBASICTYPE(MPI_LONG, long, typecnt);
216 SETUPBASICTYPE(MPI_UNSIGNED_CHAR, unsigned char, typecnt);
217 SETUPBASICTYPE(MPI_UNSIGNED_SHORT, unsigned short, typecnt);
218 SETUPBASICTYPE(MPI_UNSIGNED, unsigned, typecnt);
219 SETUPBASICTYPE(MPI_UNSIGNED_LONG, unsigned long, typecnt);
220 SETUPBASICTYPE(MPI_FLOAT, float, typecnt);
221 SETUPBASICTYPE(MPI_DOUBLE, double, typecnt);
222 SETUPBASICTYPE(MPI_BYTE, char, typecnt);
223 #ifdef HAVE_LONG_LONG_INT
224 SETUPBASICTYPE(MPI_LONG_LONG_INT, long long, typecnt);
226 #ifdef HAVE_LONG_DOUBLE
227 SETUPBASICTYPE(MPI_LONG_DOUBLE, long double, typecnt);
235 /* Generate contiguous data items */
236 SETUPCONTIGTYPE(MPI_CHAR, char, typecnt);
237 SETUPCONTIGTYPE(MPI_SHORT, short, typecnt);
238 SETUPCONTIGTYPE(MPI_INT, int, typecnt);
239 SETUPCONTIGTYPE(MPI_LONG, long, typecnt);
240 SETUPCONTIGTYPE(MPI_UNSIGNED_CHAR, unsigned char, typecnt);
241 SETUPCONTIGTYPE(MPI_UNSIGNED_SHORT, unsigned short, typecnt);
242 SETUPCONTIGTYPE(MPI_UNSIGNED, unsigned, typecnt);
243 SETUPCONTIGTYPE(MPI_UNSIGNED_LONG, unsigned long, typecnt);
244 SETUPCONTIGTYPE(MPI_FLOAT, float, typecnt);
245 SETUPCONTIGTYPE(MPI_DOUBLE, double, typecnt);
246 SETUPCONTIGTYPE(MPI_BYTE, char, typecnt);
247 #ifdef HAVE_LONG_LONG_INT
248 SETUPCONTIGTYPE(MPI_LONG_LONG_INT, long long, typecnt);
250 #ifdef HAVE_LONG_DOUBLE
251 SETUPCONTIGTYPE(MPI_LONG_DOUBLE, long double, typecnt);
254 /* Generate vector items */
255 SETUPVECTORTYPE(MPI_CHAR, char, typecnt, stride, "MPI_CHAR");
256 SETUPVECTORTYPE(MPI_SHORT, short, typecnt, stride, "MPI_SHORT");
257 SETUPVECTORTYPE(MPI_INT, int, typecnt, stride, "MPI_INT");
258 SETUPVECTORTYPE(MPI_LONG, long, typecnt, stride, "MPI_LONG");
259 SETUPVECTORTYPE(MPI_UNSIGNED_CHAR, unsigned char, typecnt, stride, "MPI_UNSIGNED_CHAR");
260 SETUPVECTORTYPE(MPI_UNSIGNED_SHORT, unsigned short, typecnt, stride, "MPI_UNSIGNED_SHORT");
261 SETUPVECTORTYPE(MPI_UNSIGNED, unsigned, typecnt, stride, "MPI_UNSIGNED");
262 SETUPVECTORTYPE(MPI_UNSIGNED_LONG, unsigned long, typecnt, stride, "MPI_UNSIGNED_LONG");
263 SETUPVECTORTYPE(MPI_FLOAT, float, typecnt, stride, "MPI_FLOAT");
264 SETUPVECTORTYPE(MPI_DOUBLE, double, typecnt, stride, "MPI_DOUBLE");
265 SETUPVECTORTYPE(MPI_BYTE, char, typecnt, stride, "MPI_BYTE");
266 #ifdef HAVE_LONG_LONG_INT
267 SETUPVECTORTYPE(MPI_LONG_LONG_INT, long long, typecnt, stride, "MPI_LONG_LONG_INT");
269 #ifdef HAVE_LONG_DOUBLE
270 SETUPVECTORTYPE(MPI_LONG_DOUBLE, long double, typecnt, stride, "MPI_LONG_DOUBLE");
273 /* Generate indexed items */
274 SETUPINDEXTYPE(MPI_CHAR, char, typecnt, "MPI_CHAR");
275 SETUPINDEXTYPE(MPI_SHORT, short, typecnt, "MPI_SHORT");
276 SETUPINDEXTYPE(MPI_INT, int, typecnt, "MPI_INT");
277 SETUPINDEXTYPE(MPI_LONG, long, typecnt, "MPI_LONG");
278 SETUPINDEXTYPE(MPI_UNSIGNED_CHAR, unsigned char, typecnt, "MPI_UNSIGNED_CHAR");
279 SETUPINDEXTYPE(MPI_UNSIGNED_SHORT, unsigned short, typecnt, "MPI_UNSIGNED_SHORT");
280 SETUPINDEXTYPE(MPI_UNSIGNED, unsigned, typecnt, "MPI_UNSIGNED");
281 SETUPINDEXTYPE(MPI_UNSIGNED_LONG, unsigned long, typecnt, "MPI_UNSIGNED_LONG");
282 SETUPINDEXTYPE(MPI_FLOAT, float, typecnt, "MPI_FLOAT");
283 SETUPINDEXTYPE(MPI_DOUBLE, double, typecnt, "MPI_DOUBLE");
284 SETUPINDEXTYPE(MPI_BYTE, char, typecnt, "MPI_BYTE");
285 #ifdef HAVE_LONG_LONG_INT
286 SETUPINDEXTYPE(MPI_LONG_LONG_INT, long long, typecnt, "MPI_LONG_LONG_INT");
288 #ifdef HAVE_LONG_DOUBLE
289 SETUPINDEXTYPE(MPI_LONG_DOUBLE, long double, typecnt, "MPI_LONG_DOUBLE");
292 /* Generate struct items */
293 SETUPSTRUCT2TYPE(MPI_CHAR, char, MPI_DOUBLE, double, typecnt, "char-double");
294 SETUPSTRUCT2TYPE(MPI_DOUBLE, double, MPI_CHAR, char, typecnt, "double-char");
295 SETUPSTRUCT2TYPE(MPI_UNSIGNED, unsigned, MPI_DOUBLE, double, typecnt, "unsigned-double");
296 SETUPSTRUCT2TYPE(MPI_FLOAT, float, MPI_LONG, long, typecnt, "float-long");
297 SETUPSTRUCT2TYPE(MPI_UNSIGNED_CHAR, unsigned char, MPI_CHAR, char, typecnt,
298 "unsigned char-char");
299 SETUPSTRUCT2TYPE(MPI_UNSIGNED_SHORT, unsigned short, MPI_DOUBLE, double,
300 typecnt, "unsigned short-double");
302 /* Generate struct using MPI_UB */
303 SETUPSTRUCTTYPEUB(MPI_CHAR, char, typecnt, stride);
304 SETUPSTRUCTTYPEUB(MPI_SHORT, short, typecnt, stride);
305 SETUPSTRUCTTYPEUB(MPI_INT, int, typecnt, stride);
306 SETUPSTRUCTTYPEUB(MPI_LONG, long, typecnt, stride);
307 SETUPSTRUCTTYPEUB(MPI_UNSIGNED_CHAR, unsigned char, typecnt, stride);
308 SETUPSTRUCTTYPEUB(MPI_UNSIGNED_SHORT, unsigned short, typecnt, stride);
309 SETUPSTRUCTTYPEUB(MPI_UNSIGNED, unsigned, typecnt, stride);
310 SETUPSTRUCTTYPEUB(MPI_UNSIGNED_LONG, unsigned long, typecnt, stride);
311 SETUPSTRUCTTYPEUB(MPI_FLOAT, float, typecnt, stride);
312 SETUPSTRUCTTYPEUB(MPI_DOUBLE, double, typecnt, stride);
313 SETUPSTRUCTTYPEUB(MPI_BYTE, char, typecnt, stride);
315 /* 60 different entries to this point + 4 for long long and
316 * 4 for long double */
321 MAX_TEST should be 1 + actual max (allows us to check that it was,
322 indeed, large enough)
325 void MTestDatatype2Allocate(MPI_Datatype ** types, void ***inbufs,
326 void ***outbufs, int **counts, int **bytesize, int *n)
328 *types = (MPI_Datatype *) malloc(MAX_TEST * sizeof(MPI_Datatype));
329 *inbufs = (void **) malloc(MAX_TEST * sizeof(void *));
330 *outbufs = (void **) malloc(MAX_TEST * sizeof(void *));
331 *counts = (int *) malloc(MAX_TEST * sizeof(int));
332 *bytesize = (int *) malloc(MAX_TEST * sizeof(int));
336 int MTestDatatype2Check(void *inbuf, void *outbuf, int size_bytes)
338 char *in = (char *) inbuf, *out = (char *) outbuf;
340 for (i = 0; i < size_bytes; i++) {
341 if (in[i] != out[i]) {
349 * This is a version of CheckData that prints error messages
351 int MtestDatatype2CheckAndPrint(void *inbuf, void *outbuf, int size_bytes,
352 char *typename, int typenum)
354 int errloc, world_rank;
356 if ((errloc = MTestDatatype2Check(inbuf, outbuf, size_bytes))) {
358 MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
360 "Error in data with type %s (type %d on %d) at byte %d of %d\n",
361 typename, typenum, world_rank, errloc - 1, size_bytes);
363 p2 = (char *) outbuf;
364 fprintf(stderr, "Got %x expected %x\n", p2[errloc - 1], p1[errloc - 1]);
369 void MTestDatatype2Free(MPI_Datatype * types, void **inbufs, void **outbufs,
370 int *counts, int *bytesize, int n)
373 for (i = 0; i < n; i++) {
378 /* Only if not basic ... */
379 if (i >= nbasic_types)
380 MPI_Type_free(types + i);