Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
handle nested datatypes in smpi (structs of vectors for example), which previously...
[simgrid.git] / teshsuite / smpi / mpich-test / pt2pt / dtypes.c
1 /* This file contains code to generate a variety of MPI datatypes for testing
2    the various MPI routines. 
3
4  To simplify the test code, this generates an array of datatypes, buffers with
5  data and buffers with no data (0 bits) for use in send and receive 
6  routines of various types.
7
8   In addition, this doesn't even test all of the possibilities.  For example,
9   there is currently no test of sending more than one item defined with 
10   MPI_Type_contiguous .
11
12   This routine should be extended as time permits.
13
14   Note also that this test assumes that the sending and receive types are
15   the same.  MPI requires only that the type signatures match, which is
16   a weaker requirement.
17
18   THIS CODE IS FROM mpich/tsuite AND SHOULD BE CHANGED THERE ONLY
19  */
20
21 #include "mpi.h"
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include "dtypes.h"
25
26 #if defined(NEEDS_STDLIB_PROTOTYPES)
27 #include "protofix.h"
28 #endif
29
30 /* Change this to test only the basic, predefined types */
31 static int basic_only = 0;
32
33 /* 
34    Arrays types, inbufs, outbufs, and counts are allocated by the
35    CALLER.  n on input is the maximum number; on output, it is the
36    number defined .
37    names contains a string identifying the test
38
39    See AllocateForData below for a routine to allocate these arrays.
40
41    We may want to add a routine to call to check that the proper data
42    has been received.
43  */
44 /* TYPECNT is the number of instances of each type in a test */
45 #define TYPECNT 10
46 #define SETUPBASICTYPE(mpi,c,name) { int i; c *a; \
47 if (cnt > *n) {*n = cnt; return; }\
48 types[cnt] = mpi; \
49 inbufs[cnt] = (void *)calloc( TYPECNT,sizeof(c) ); \
50 outbufs[cnt] = (void *)malloc( sizeof(c) * TYPECNT ); \
51 a = (c *)inbufs[cnt]; for (i=0; i<TYPECNT; i++) a[i] = i; \
52 a = (c *)outbufs[cnt]; for (i=0; i<TYPECNT; i++) a[i] = 0; \
53 names[cnt] = (char *)malloc(100);\
54 sprintf( names[cnt], "Basic type %s", name );\
55 counts[cnt]  = TYPECNT; bytesize[cnt] = sizeof(c) * TYPECNT; cnt++; }
56
57 #define SETUPCONTIGTYPE(mpi,c,name) { int i; c *a; \
58 if (cnt > *n) {*n = cnt; return; }\
59 MPI_Type_contiguous( TYPECNT, mpi, types + cnt );\
60 MPI_Type_commit( types + cnt );\
61 inbufs[cnt] = (void *)calloc( TYPECNT, sizeof(c) ); \
62 outbufs[cnt] = (void *)malloc( sizeof(c) * TYPECNT ); \
63 a = (c *)inbufs[cnt]; for (i=0; i<TYPECNT; i++) a[i] = i; \
64 a = (c *)outbufs[cnt]; for (i=0; i<TYPECNT; i++) a[i] = 0; \
65 names[cnt] = (char *)malloc(100);\
66 sprintf( names[cnt], "Contig type %s", name );\
67 counts[cnt]  = 1;  bytesize[cnt] = sizeof(c) * TYPECNT; cnt++; }
68
69 /* These are vectors of block length one.  */
70 #define STRIDE 9
71 #define SETUPVECTORTYPE(mpi,c,name) { int i; c *a; \
72 if (cnt > *n) {*n = cnt; return; }\
73 MPI_Type_vector( TYPECNT, 1, STRIDE, mpi, types + cnt );\
74 MPI_Type_commit( types + cnt );\
75 inbufs[cnt] = (void *)calloc( sizeof(c) * TYPECNT * STRIDE,1); \
76 outbufs[cnt] = (void *)calloc( sizeof(c) * TYPECNT * STRIDE,1); \
77 a = (c *)inbufs[cnt]; for (i=0; i<TYPECNT; i++) a[i*STRIDE] = i; \
78 a = (c *)outbufs[cnt]; for (i=0; i<TYPECNT; i++) a[i*STRIDE] = 0; \
79 names[cnt] = (char *)malloc(100);\
80 sprintf( names[cnt], "Vector type %s", name );\
81 counts[cnt]  = 1;  bytesize[cnt] = sizeof(c) * TYPECNT * STRIDE ;cnt++; }
82
83 /* This indexed type is setup like a contiguous type .
84    Note that systems may try to convert this to contiguous, so we'll
85    eventually need a test that has holes in it */
86 #define SETUPINDEXTYPE(mpi,c,name) { int i; int *lens, *disp; c *a; \
87 if (cnt > *n) {*n = cnt; return; }\
88 lens = (int *)malloc( TYPECNT * sizeof(int) ); \
89 disp = (int *)malloc( TYPECNT * sizeof(int) ); \
90 for (i=0; i<TYPECNT; i++) { lens[i] = 1; disp[i] = i; } \
91 MPI_Type_indexed( TYPECNT, lens, disp, mpi, types + cnt );\
92 free( lens ); free( disp ); \
93 MPI_Type_commit( types + cnt );\
94 inbufs[cnt] = (void *)calloc( TYPECNT, sizeof(c) ); \
95 outbufs[cnt] = (void *)malloc( sizeof(c) * TYPECNT ); \
96 a = (c *)inbufs[cnt]; for (i=0; i<TYPECNT; i++) a[i] = i; \
97 a = (c *)outbufs[cnt]; for (i=0; i<TYPECNT; i++) a[i] = 0; \
98 names[cnt] = (char *)malloc(100);\
99 sprintf( names[cnt], "Index type %s", name );\
100 counts[cnt]  = 1;  bytesize[cnt] = sizeof(c) * TYPECNT; cnt++; }
101
102 /* This defines a structure of two basic members; by chosing things like
103    (char, double), various packing and alignment tests can be made */
104 #define SETUPSTRUCT2TYPE(mpi1,c1,mpi2,c2,name,tname) { int i; \
105 MPI_Datatype b[3]; int cnts[3]; \
106 struct name { c1 a1; c2 a2; } *a, samp; \
107 MPI_Aint disp[3]; \
108 b[0] = mpi1; b[1] = mpi2; b[2] = MPI_UB;\
109 cnts[0] = 1; cnts[1] = 1; cnts[2] = 1;\
110 MPI_Address( &(samp.a2), &disp[1] ); \
111 MPI_Address( &(samp.a1), &disp[0] ); \
112 MPI_Address( &(samp) + 1, &disp[2] ); \
113 disp[1] = disp[1] - disp[0]; disp[2] = disp[2] - disp[0]; disp[0] = 0; \
114 if (cnt > *n) {*n = cnt; return; }\
115 MPI_Type_struct( 3, cnts, disp, b, types + cnt );\
116 MPI_Type_commit( types + cnt );\
117 inbufs[cnt] = (void *)calloc( sizeof(struct name) * TYPECNT,1); \
118 outbufs[cnt] = (void *)calloc( sizeof(struct name) * TYPECNT,1); \
119 a = (struct name *)inbufs[cnt]; for (i=0; i<TYPECNT; i++) { a[i].a1 = i; \
120  a[i].a2 = i; } \
121 a = (struct name *)outbufs[cnt]; for (i=0; i<TYPECNT; i++) { a[i].a1 = 0; \
122  a[i].a2 = 0; } \
123 names[cnt] = (char *)malloc(100);\
124 sprintf( names[cnt], "Struct type %s", tname );\
125 counts[cnt]  = TYPECNT;  bytesize[cnt] = sizeof(struct name) * TYPECNT;cnt++; }
126
127 /* This accomplished the same effect as VECTOR, but allow a count of > 1 */
128 #define SETUPSTRUCTTYPEUB(mpi,c,name) { int i; c *a; \
129 int blens[2];  MPI_Aint disps[2]; MPI_Datatype mtypes[2]; \
130 if (cnt > *n) {*n = cnt; return; }\
131 blens[0] = 1; blens[1] = 1; disps[0] = 0; disps[1] = STRIDE * sizeof(c); \
132 mtypes[0] = mpi; mtypes[1] = MPI_UB; \
133 MPI_Type_struct( 2, blens, disps, mtypes, types + cnt );\
134 MPI_Type_commit( types + cnt );\
135 inbufs[cnt] = (void *)calloc( sizeof(c) * TYPECNT * STRIDE,1); \
136 outbufs[cnt] = (void *)calloc( sizeof(c) * TYPECNT * STRIDE,1); \
137 a = (c *)inbufs[cnt]; for (i=0; i<TYPECNT; i++) a[i*STRIDE] = i; \
138 a = (c *)outbufs[cnt]; for (i=0; i<TYPECNT; i++) a[i*STRIDE] = 0; \
139 names[cnt] = (char *)malloc(100);\
140 sprintf( names[cnt], "Struct (MPI_UB) type %s", name );\
141 counts[cnt]  = TYPECNT;  bytesize[cnt] = sizeof(c) * TYPECNT * STRIDE;cnt++; }
142
143 /* 
144  * Set whether only the basic types should be generated
145  */
146 void BasicDatatypesOnly( void )
147 {
148     basic_only = 1;
149 }
150
151 static int nbasic_types = 0;
152 /* On input, n is the size of the various buffers.  On output, 
153    it is the number available types 
154  */
155 void GenerateData( MPI_Datatype *types, void **inbufs, void **outbufs, 
156                    int *counts, int *bytesize, char **names, int *n )
157 {
158 int cnt = 0;   /* Number of defined types */
159
160 /* First, generate an element of each basic type */
161 SETUPBASICTYPE(MPI_CHAR,char,"MPI_CHAR");
162 SETUPBASICTYPE(MPI_SHORT,short,"MPI_SHORT");
163 SETUPBASICTYPE(MPI_INT,int,"MPI_INT");
164 SETUPBASICTYPE(MPI_LONG,long,"MPI_LONG");
165 SETUPBASICTYPE(MPI_UNSIGNED_CHAR,unsigned char,"MPI_UNSIGNED_CHAR");
166 SETUPBASICTYPE(MPI_UNSIGNED_SHORT,unsigned short,"MPI_UNSIGNED_SHORT");
167 SETUPBASICTYPE(MPI_UNSIGNED,unsigned,"MPI_UNSIGNED");
168 SETUPBASICTYPE(MPI_UNSIGNED_LONG,unsigned long,"MPI_UNSIGNED_LONG");
169 SETUPBASICTYPE(MPI_FLOAT,float,"MPI_FLOAT");
170 SETUPBASICTYPE(MPI_DOUBLE,double,"MPI_DOUBLE");
171 SETUPBASICTYPE(MPI_BYTE,char,"MPI_BYTE");
172 #ifdef HAVE_LONG_LONG_INT
173 SETUPBASICTYPE(MPI_LONG_LONG_INT,long long,"MPI_LONG_LONG_INT");
174 #endif
175 #ifdef HAVE_LONG_DOUBLE
176 SETUPBASICTYPE(MPI_LONG_DOUBLE,long double,"MPI_LONG_DOUBLE");
177 #endif
178 nbasic_types = cnt;
179
180  if (basic_only) {
181      *n = cnt;
182      return;
183  }
184 /* Generate contiguous data items */
185 SETUPCONTIGTYPE(MPI_CHAR,char,"MPI_CHAR");
186 SETUPCONTIGTYPE(MPI_SHORT,short,"MPI_SHORT");
187 SETUPCONTIGTYPE(MPI_INT,int,"MPI_INT");
188 SETUPCONTIGTYPE(MPI_LONG,long,"MPI_LONG");
189 SETUPCONTIGTYPE(MPI_UNSIGNED_CHAR,unsigned char,"MPI_UNSIGNED_CHAR");
190 SETUPCONTIGTYPE(MPI_UNSIGNED_SHORT,unsigned short,"MPI_UNSIGNED_SHORT");
191 SETUPCONTIGTYPE(MPI_UNSIGNED,unsigned,"MPI_UNSIGNED");
192 SETUPCONTIGTYPE(MPI_UNSIGNED_LONG,unsigned long,"MPI_UNSIGNED_LONG");
193 SETUPCONTIGTYPE(MPI_FLOAT,float,"MPI_FLOAT");
194 SETUPCONTIGTYPE(MPI_DOUBLE,double,"MPI_DOUBLE");
195 SETUPCONTIGTYPE(MPI_BYTE,char,"MPI_BYTE");
196 #ifdef HAVE_LONG_LONG_INT
197 SETUPCONTIGTYPE(MPI_LONG_LONG_INT,long long,"MPI_LONG_LONG_INT");
198 #endif
199 #ifdef HAVE_LONG_DOUBLE
200 SETUPCONTIGTYPE(MPI_LONG_DOUBLE,long double,"MPI_LONG_DOUBLE");
201 #endif
202
203 /* Generate vector items */
204 SETUPVECTORTYPE(MPI_CHAR,char,"MPI_CHAR");
205 SETUPVECTORTYPE(MPI_SHORT,short,"MPI_SHORT");
206 SETUPVECTORTYPE(MPI_INT,int,"MPI_INT");
207 SETUPVECTORTYPE(MPI_LONG,long,"MPI_LONG");
208 SETUPVECTORTYPE(MPI_UNSIGNED_CHAR,unsigned char,"MPI_UNSIGNED_CHAR");
209 SETUPVECTORTYPE(MPI_UNSIGNED_SHORT,unsigned short,"MPI_UNSIGNED_SHORT");
210 SETUPVECTORTYPE(MPI_UNSIGNED,unsigned,"MPI_UNSIGNED");
211 SETUPVECTORTYPE(MPI_UNSIGNED_LONG,unsigned long,"MPI_UNSIGNED_LONG");
212 SETUPVECTORTYPE(MPI_FLOAT,float,"MPI_FLOAT");
213 SETUPVECTORTYPE(MPI_DOUBLE,double,"MPI_DOUBLE");
214 SETUPVECTORTYPE(MPI_BYTE,char,"MPI_BYTE");
215 #ifdef HAVE_LONG_LONG_INT
216 SETUPVECTORTYPE(MPI_LONG_LONG_INT,long long,"MPI_LONG_LONG_INT");
217 #endif
218 #ifdef HAVE_LONG_DOUBLE
219 SETUPVECTORTYPE(MPI_LONG_DOUBLE,long double,"MPI_LONG_DOUBLE");
220 #endif
221
222 /* Generate indexed items */
223 SETUPINDEXTYPE(MPI_CHAR,char,"MPI_CHAR");
224 SETUPINDEXTYPE(MPI_SHORT,short,"MPI_SHORT");
225 SETUPINDEXTYPE(MPI_INT,int,"MPI_INT");
226 SETUPINDEXTYPE(MPI_LONG,long,"MPI_LONG");
227 SETUPINDEXTYPE(MPI_UNSIGNED_CHAR,unsigned char,"MPI_UNSIGNED_CHAR");
228 SETUPINDEXTYPE(MPI_UNSIGNED_SHORT,unsigned short,"MPI_UNSIGNED_SHORT");
229 SETUPINDEXTYPE(MPI_UNSIGNED,unsigned,"MPI_UNSIGNED");
230 SETUPINDEXTYPE(MPI_UNSIGNED_LONG,unsigned long,"MPI_UNSIGNED_LONG");
231 SETUPINDEXTYPE(MPI_FLOAT,float,"MPI_FLOAT");
232 SETUPINDEXTYPE(MPI_DOUBLE,double,"MPI_DOUBLE");
233 SETUPINDEXTYPE(MPI_BYTE,char,"MPI_BYTE");
234 #ifdef HAVE_LONG_LONG_INT
235 SETUPINDEXTYPE(MPI_LONG_LONG_INT,long long,"MPI_LONG_LONG_INT");
236 #endif
237 #ifdef HAVE_LONG_DOUBLE
238 SETUPINDEXTYPE(MPI_LONG_DOUBLE,long double,"MPI_LONG_DOUBLE");
239 #endif
240
241 /* Generate struct items */ 
242 SETUPSTRUCT2TYPE(MPI_CHAR,char,MPI_DOUBLE,double,d1,"char-double")
243 SETUPSTRUCT2TYPE(MPI_DOUBLE,double,MPI_CHAR,char,d2,"double-char")
244 SETUPSTRUCT2TYPE(MPI_UNSIGNED,unsigned,MPI_DOUBLE,double,d3,"unsigned-double")
245 SETUPSTRUCT2TYPE(MPI_FLOAT,float,MPI_LONG,long,d4,"float-long")
246 SETUPSTRUCT2TYPE(MPI_UNSIGNED_CHAR,unsigned char,MPI_CHAR,char,d5,
247   "unsigned char-char")
248 SETUPSTRUCT2TYPE(MPI_UNSIGNED_SHORT,unsigned short,MPI_DOUBLE,double,d6,
249   "unsigned short-double")
250
251 /* Generate struct using MPI_UB */
252 SETUPSTRUCTTYPEUB(MPI_CHAR,char,"MPI_CHAR");
253 SETUPSTRUCTTYPEUB(MPI_SHORT,short,"MPI_SHORT");
254 SETUPSTRUCTTYPEUB(MPI_INT,int,"MPI_INT");
255 SETUPSTRUCTTYPEUB(MPI_LONG,long,"MPI_LONG");
256 SETUPSTRUCTTYPEUB(MPI_UNSIGNED_CHAR,unsigned char,"MPI_UNSIGNED_CHAR");
257 SETUPSTRUCTTYPEUB(MPI_UNSIGNED_SHORT,unsigned short,"MPI_UNSIGNED_SHORT");
258 SETUPSTRUCTTYPEUB(MPI_UNSIGNED,unsigned,"MPI_UNSIGNED");
259 SETUPSTRUCTTYPEUB(MPI_UNSIGNED_LONG,unsigned long,"MPI_UNSIGNED_LONG");
260 SETUPSTRUCTTYPEUB(MPI_FLOAT,float,"MPI_FLOAT");
261 SETUPSTRUCTTYPEUB(MPI_DOUBLE,double,"MPI_DOUBLE");
262 SETUPSTRUCTTYPEUB(MPI_BYTE,char,"MPI_BYTE");
263
264 /* 60 different entries to this point + 4 for long long and 
265    4 for long double */
266 *n = cnt;
267 }
268
269 /* 
270    MAX_TEST should be 1 + actual max (allows us to check that it was, 
271    indeed, large enough) 
272  */
273 #define MAX_TEST 70
274 void AllocateForData( MPI_Datatype **types, void ***inbufs, void ***outbufs, 
275                       int **counts, int **bytesize, char ***names, int *n )
276 {
277     *types    = (MPI_Datatype *)malloc( MAX_TEST * sizeof(MPI_Datatype) );
278     *inbufs   = (void **) malloc( MAX_TEST * sizeof(void *) );
279     *outbufs  = (void **) malloc( MAX_TEST * sizeof(void *) );
280     *names    = (char **) malloc( MAX_TEST * sizeof(char *) );
281     *counts   = (int *)   malloc( MAX_TEST * sizeof(int) );
282     *bytesize = (int *)   malloc( MAX_TEST * sizeof(int) );
283     *n        = MAX_TEST;
284 }
285
286 int CheckData( void *inbuf, void *outbuf, int size_bytes )
287 {
288     char *in = (char *)inbuf, *out = (char *)outbuf;
289     int  i;
290     for (i=0; i<size_bytes; i++) {
291         if (in[i] != out[i]) {
292             return i + 1;
293         }
294     }
295     return 0;
296 }
297
298 /* 
299  * This is a version of CheckData that prints error messages
300  */
301 int CheckDataAndPrint( void *inbuf, void *outbuf, int size_bytes, 
302                        char *typename, int typenum )
303 {
304     int errloc, world_rank;
305     
306     if ((errloc = CheckData( inbuf, outbuf, size_bytes ))) {
307         char *p1, *p2;
308         MPI_Comm_rank( MPI_COMM_WORLD, &world_rank );
309         fprintf( stderr, 
310          "Error in data with type %s (type %d on %d) at byte %d of %d\n", 
311                  typename, typenum, world_rank, errloc - 1, size_bytes );
312         p1 = (char *)inbuf;
313         p2 = (char *)outbuf;
314         fprintf( stderr, 
315                  "Got %x expected %x\n", p2[errloc-1], p1[errloc-1] );
316 #if 0
317         MPIR_PrintDatatypeUnpack( stderr, counts[j], types[j], 
318                                   0, 0 );
319 #endif
320     }
321     return errloc;
322 }
323
324 void FreeDatatypes( MPI_Datatype *types, void **inbufs, void **outbufs, 
325                     int *counts, int *bytesize, char **names, int n )
326 {
327     int i;
328     for (i=0; i<n; i++) {
329         if (inbufs[i]) 
330             free( inbufs[i] );
331         if (outbufs[i]) 
332             free( outbufs[i] );
333         free( names[i] );
334         /* Only if not basic ... */
335         if (i >= nbasic_types) 
336             MPI_Type_free( types + i );
337     }
338     free( inbufs );
339     free( outbufs );
340     free( names );
341     free( counts );
342     free( bytesize );
343 }