1 /* This file contains code to generate a variety of MPI datatypes for testing
2 the various MPI routines.
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.
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
12 This routine should be extended as time permits.
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
18 THIS CODE IS FROM mpich/tsuite AND SHOULD BE CHANGED THERE ONLY
26 #if defined(NEEDS_STDLIB_PROTOTYPES)
30 /* Change this to test only the basic, predefined types */
31 static int basic_only = 0;
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
37 names contains a string identifying the test
39 See AllocateForData below for a routine to allocate these arrays.
41 We may want to add a routine to call to check that the proper data
44 /* TYPECNT is the number of instances of each type in a test */
46 #define SETUPBASICTYPE(mpi,c,name) { int i; c *a; \
47 if (cnt > *n) {*n = cnt; return; }\
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++; }
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++; }
69 /* These are vectors of block length one. */
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++; }
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++; }
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; \
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; \
121 a = (struct name *)outbufs[cnt]; for (i=0; i<TYPECNT; i++) { a[i].a1 = 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++; }
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++; }
144 * Set whether only the basic types should be generated
146 void BasicDatatypesOnly( void )
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
155 void GenerateData( MPI_Datatype *types, void **inbufs, void **outbufs,
156 int *counts, int *bytesize, char **names, int *n )
158 int cnt = 0; /* Number of defined types */
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");
175 #ifdef HAVE_LONG_DOUBLE
176 SETUPBASICTYPE(MPI_LONG_DOUBLE,long double,"MPI_LONG_DOUBLE");
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");
199 #ifdef HAVE_LONG_DOUBLE
200 SETUPCONTIGTYPE(MPI_LONG_DOUBLE,long double,"MPI_LONG_DOUBLE");
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");
218 #ifdef HAVE_LONG_DOUBLE
219 SETUPVECTORTYPE(MPI_LONG_DOUBLE,long double,"MPI_LONG_DOUBLE");
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");
237 #ifdef HAVE_LONG_DOUBLE
238 SETUPINDEXTYPE(MPI_LONG_DOUBLE,long double,"MPI_LONG_DOUBLE");
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")
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");
264 /* 60 different entries to this point + 4 for long long and
270 MAX_TEST should be 1 + actual max (allows us to check that it was,
271 indeed, large enough)
274 void AllocateForData( MPI_Datatype **types, void ***inbufs, void ***outbufs,
275 int **counts, int **bytesize, char ***names, int *n )
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) );
286 int CheckData( void *inbuf, void *outbuf, int size_bytes )
288 char *in = (char *)inbuf, *out = (char *)outbuf;
290 for (i=0; i<size_bytes; i++) {
291 if (in[i] != out[i]) {
299 * This is a version of CheckData that prints error messages
301 int CheckDataAndPrint( void *inbuf, void *outbuf, int size_bytes,
302 char *typename, int typenum )
304 int errloc, world_rank;
306 if ((errloc = CheckData( inbuf, outbuf, size_bytes ))) {
308 MPI_Comm_rank( MPI_COMM_WORLD, &world_rank );
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 );
315 "Got %x expected %x\n", p2[errloc-1], p1[errloc-1] );
317 MPIR_PrintDatatypeUnpack( stderr, counts[j], types[j],
324 void FreeDatatypes( MPI_Datatype *types, void **inbufs, void **outbufs,
325 int *counts, int *bytesize, char **names, int n )
328 for (i=0; i<n; i++) {
334 /* Only if not basic ... */
335 if (i >= nbasic_types)
336 MPI_Type_free( types + i );