Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' into fix/execute_benched
[simgrid.git] / teshsuite / smpi / mpich3-test / util / dtypes_manual.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 SMPI_VARINIT_GLOBAL_AND_SET(basic_only, int, 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 /*
60    Add a predefined MPI type to the tests.  _count instances of the
61    type will be sent.
62 */
63 #define SETUPBASICTYPE(_mpitype,_ctype,_count) { \
64   int i; _ctype *a;     \
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++; }
72
73 /*
74    Add a contiguous version of a predefined type.  Send one instance of
75    the type which contains _count copies of the predefined type.
76  */
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); \
91   free(myname); \
92   counts[cnt]  = 1;  bytesize[cnt] = sizeof(_ctype) * (_count); cnt++; }
93
94 /*
95   Create a vector with _count elements, separated by stride _stride,
96   of _mpitype.  Each block has a single element.
97  */
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); \
112   free(myname); \
113   counts[cnt]  = 1; bytesize[cnt] = sizeof(_ctype) * (_count) * (_stride) ;\
114   cnt++; }
115
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); \
137   free(myname); \
138   counts[cnt]  = 1;  bytesize[cnt] = sizeof(_ctype) * (_count); cnt++; }
139
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;     \
146   MPI_Aint disp[3];                             \
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; \
159       a[i].a2 = i; }                                                    \
160   a = (struct name *)outbufs[cnt]; for (i=0; i<(_count); i++) { a[i].a1 = 0; \
161       a[i].a2 = 0; }                                                    \
162   myname = (char *)malloc(100);                                 \
163   snprintf(myname, 100, "Struct type %s", _tname);              \
164   MPI_Type_set_name(types[cnt], myname); \
165   free(myname); \
166   counts[cnt]  = (_count);  bytesize[cnt] = sizeof(struct name) * (_count);cnt++; }
167
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); \
187   free(myname); \
188   counts[cnt]  = (_count);  \
189   bytesize[cnt] = sizeof(_ctype) * (_count) * (_stride);\
190   cnt++; }
191
192 /*
193  * Set whether only the basic types should be generated
194  */
195 void MTestDatatype2BasicOnly(void)
196 {
197     SMPI_VARGET_GLOBAL(basic_only) = 1;
198 }
199
200 SMPI_VARINIT_GLOBAL_AND_SET(nbasic_types, int, 0);  /* World rank */
201 /* On input, n is the size of the various buffers.  On output,
202    it is the number available types
203  */
204 void MTestDatatype2Generate(MPI_Datatype * types, void **inbufs, void **outbufs,
205                             int *counts, int *bytesize, int *n)
206 {
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 */
210
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);
225 #endif
226 #ifdef HAVE_LONG_DOUBLE
227     SETUPBASICTYPE(MPI_LONG_DOUBLE, long double, typecnt);
228 #endif
229     SMPI_VARGET_GLOBAL(nbasic_types) = cnt;
230
231     if (SMPI_VARGET_GLOBAL(basic_only)) {
232         *n = cnt;
233         return;
234     }
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);
249 #endif
250 #ifdef HAVE_LONG_DOUBLE
251     SETUPCONTIGTYPE(MPI_LONG_DOUBLE, long double, typecnt);
252 #endif
253
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");
268 #endif
269 #ifdef HAVE_LONG_DOUBLE
270     SETUPVECTORTYPE(MPI_LONG_DOUBLE, long double, typecnt, stride, "MPI_LONG_DOUBLE");
271 #endif
272
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");
287 #endif
288 #ifdef HAVE_LONG_DOUBLE
289     SETUPINDEXTYPE(MPI_LONG_DOUBLE, long double, typecnt, "MPI_LONG_DOUBLE");
290 #endif
291
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");
301
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);
314
315     /* 60 different entries to this point + 4 for long long and
316      * 4 for long double */
317     *n = cnt;
318 }
319
320 /*
321    MAX_TEST should be 1 + actual max (allows us to check that it was,
322    indeed, large enough)
323  */
324 #define MAX_TEST 70
325 void MTestDatatype2Allocate(MPI_Datatype ** types, void ***inbufs,
326                             void ***outbufs, int **counts, int **bytesize, int *n)
327 {
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));
333     *n = MAX_TEST;
334 }
335
336 int MTestDatatype2Check(void *inbuf, void *outbuf, int size_bytes)
337 {
338     char *in = (char *) inbuf, *out = (char *) outbuf;
339     int i;
340     for (i = 0; i < size_bytes; i++) {
341         if (in[i] != out[i]) {
342             return i + 1;
343         }
344     }
345     return 0;
346 }
347
348 /*
349  * This is a version of CheckData that prints error messages
350  */
351 static int MtestDatatype2CheckAndPrint(void *inbuf, void *outbuf, int size_bytes,
352                                 char *typename, int typenum)
353 {
354     int errloc, world_rank;
355
356     if ((errloc = MTestDatatype2Check(inbuf, outbuf, size_bytes))) {
357         char *p1, *p2;
358         MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
359         fprintf(stderr,
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);
362         p1 = (char *) inbuf;
363         p2 = (char *) outbuf;
364         fprintf(stderr, "Got %hhx expected %hhx\n", p2[errloc - 1], p1[errloc - 1]);
365     }
366     return errloc;
367 }
368
369 void MTestDatatype2Free(MPI_Datatype * types, void **inbufs, void **outbufs,
370                         int *counts, int *bytesize, int n)
371 {
372     int i;
373     for (i = 0; i < n; i++) {
374         if (inbufs[i])
375             free(inbufs[i]);
376         if (outbufs[i])
377             free(outbufs[i]);
378         /* Only if not basic ... */
379         if (i >= SMPI_VARGET_GLOBAL(nbasic_types))
380             MPI_Type_free(types + i);
381     }
382     free(types);
383     free(inbufs);
384     free(outbufs);
385     free(counts);
386     free(bytesize);
387 }