Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
reduce some tests duration as comm_create takes longer now (comms)
[simgrid.git] / teshsuite / smpi / mpich3-test / util / dtypes.c
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  *
4  *  (C) 2014 by Argonne National Laboratory.
5  *      See COPYRIGHT in top-level directory.
6  */
7 #include "mpi.h"
8 #include "mpitestconf.h"
9 #include "mpitest.h"
10 #include "dtypes.h"
11 #if defined(HAVE_STDIO_H) || defined(STDC_HEADERS)
12 #include <stdio.h>
13 #endif
14 #if defined(HAVE_STDLIB_H) || defined(STDC_HEADERS)
15 #include <stdlib.h>
16 #endif
17 #if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
18 #include <string.h>
19 #endif
20 #ifdef HAVE_STDARG_H
21 #include <stdarg.h>
22 #endif
23
24 /* This file contains code to generate a variety of MPI datatypes for testing
25    the various MPI routines.
26
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.
30
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
33    MPI_Type_contiguous .
34
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
37    a weaker requirement.
38
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.
42
43  */
44
45 /* Change this to test only the basic, predefined types */
46 static int basic_only = 0;
47
48 /*
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
51    number defined.
52
53    See MTestDatatype2Allocate below for a routine to allocate these arrays.
54
55    We may want to add a routine to call to check that the proper data
56    has been received.
57  */
58
59 #define STR_SIZE 200
60
61 /*
62    Add a predefined MPI type to the tests.  _count instances of the
63    type will be sent.
64 */
65 #define SETUPBASICTYPE(_mpitype,_ctype,_count) { \
66   int i; _ctype *a;     \
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++; }
74
75 /*
76    Add a contiguous version of a predefined type.  Send one instance of
77    the type which contains _count copies of the predefined type.
78  */
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); \
93   free(myname); \
94   counts[cnt]  = 1;  bytesize[cnt] = sizeof(_ctype) * (_count); cnt++; }
95
96 /*
97   Create a vector with _count elements, separated by stride _stride,
98   of _mpitype.  Each block has a single element.
99  */
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); \
114   free(myname); \
115   counts[cnt]  = 1; bytesize[cnt] = sizeof(_ctype) * (_count) * (_stride) ;\
116   cnt++; }
117
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); \
139   free(myname); \
140   counts[cnt]  = 1;  bytesize[cnt] = sizeof(_ctype) * (_count); cnt++; }
141
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;     \
148   MPI_Aint disp[3];                             \
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; \
161       a[i].a2 = i; }                                                    \
162   a = (struct name *)outbufs[cnt]; for (i=0; i<(_count); i++) { a[i].a1 = 0; \
163       a[i].a2 = 0; }                                                    \
164   myname = (char *)malloc(STR_SIZE);                                    \
165   snprintf(myname, STR_SIZE, "Struct type %s", _tname);         \
166   MPI_Type_set_name(types[cnt], myname); \
167   free(myname); \
168   counts[cnt]  = (_count);  bytesize[cnt] = sizeof(struct name) * (_count);cnt++; }
169
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); \
189   free(myname); \
190   counts[cnt]  = (_count);  \
191   bytesize[cnt] = sizeof(_ctype) * (_count) * (_stride);\
192   cnt++; }
193
194 /*
195  * Set whether only the basic types should be generated
196  */
197 void MTestDatatype2BasicOnly(void)
198 {
199     basic_only = 1;
200 }
201
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
205  */
206 void MTestDatatype2Generate(MPI_Datatype * types, void **inbufs, void **outbufs,
207                             int *counts, int *bytesize, int *n)
208 {
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 */
212
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);
227 #endif
228 #ifdef HAVE_LONG_DOUBLE
229     SETUPBASICTYPE(MPI_LONG_DOUBLE, long double, typecnt);
230 #endif
231     nbasic_types = cnt;
232
233     if (basic_only) {
234         *n = cnt;
235         return;
236     }
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);
251 #endif
252 #ifdef HAVE_LONG_DOUBLE
253     SETUPCONTIGTYPE(MPI_LONG_DOUBLE, long double, typecnt);
254 #endif
255
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");
270 #endif
271 #ifdef HAVE_LONG_DOUBLE
272     SETUPVECTORTYPE(MPI_LONG_DOUBLE, long double, typecnt, stride, "MPI_LONG_DOUBLE");
273 #endif
274
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");
289 #endif
290 #ifdef HAVE_LONG_DOUBLE
291     SETUPINDEXTYPE(MPI_LONG_DOUBLE, long double, typecnt, "MPI_LONG_DOUBLE");
292 #endif
293
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");
303
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);
316
317     /* 60 different entries to this point + 4 for long long and
318      * 4 for long double */
319     *n = cnt;
320 }
321
322 /*
323    MAX_TEST should be 1 + actual max (allows us to check that it was,
324    indeed, large enough)
325  */
326 #define MAX_TEST 70
327 void MTestDatatype2Allocate(MPI_Datatype ** types, void ***inbufs,
328                             void ***outbufs, int **counts, int **bytesize, int *n)
329 {
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));
335     *n = MAX_TEST;
336 }
337
338 int MTestDatatype2Check(void *inbuf, void *outbuf, int size_bytes)
339 {
340     char *in = (char *) inbuf, *out = (char *) outbuf;
341     int i;
342     for (i = 0; i < size_bytes; i++) {
343         if (in[i] != out[i]) {
344             return i + 1;
345         }
346     }
347     return 0;
348 }
349
350 /*
351  * This is a version of CheckData that prints error messages
352  */
353 static int MtestDatatype2CheckAndPrint(void *inbuf, void *outbuf, int size_bytes,
354                                 char *typename, int typenum)
355 {
356     int errloc, world_rank;
357
358     if ((errloc = MTestDatatype2Check(inbuf, outbuf, size_bytes))) {
359         char *p1, *p2;
360         MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
361         fprintf(stderr,
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);
364         p1 = (char *) inbuf;
365         p2 = (char *) outbuf;
366         fprintf(stderr, "Got %hhx expected %hhx\n", p2[errloc - 1], p1[errloc - 1]);
367     }
368     return errloc;
369 }
370
371 void MTestDatatype2Free(MPI_Datatype * types, void **inbufs, void **outbufs,
372                         int *counts, int *bytesize, int n)
373 {
374     int i;
375     for (i = 0; i < n; i++) {
376         if (inbufs[i])
377             free(inbufs[i]);
378         if (outbufs[i])
379             free(outbufs[i]);
380         /* Only if not basic ... */
381         if (i >= nbasic_types)
382             MPI_Type_free(types + i);
383     }
384     free(types);
385     free(inbufs);
386     free(outbufs);
387     free(counts);
388     free(bytesize);
389 }