blob: bac0be4af58dd1ee0dbc79816d720da3c3721b07 [file] [log] [blame]
sewardj6ec98e82006-03-10 21:48:29 +00001
2/* A test program to check whether the type-traversal functions in
3 mpiwrap.c (walk_type, walk_type_array) are correct. It does this
4 by sending a message to itself, thereby discovering what areas of
5 memory the MPI implementation itself believe constitute the type.
6 It then gets walk_type to enumerate the type, and compares the
7 results. */
8
9#include <stdio.h>
10#include <stdlib.h>
sewardjb4017222006-11-23 15:14:18 +000011#include <string.h>
sewardj6ec98e82006-03-10 21:48:29 +000012#include <assert.h>
sewardj6ec98e82006-03-10 21:48:29 +000013#include "mpi.h"
sewardj6f97a1b2006-03-10 22:17:02 +000014#include "../memcheck/memcheck.h"
sewardj6ec98e82006-03-10 21:48:29 +000015
16typedef MPI_Datatype Ty;
17
18typedef unsigned char Bool;
19#define False ((Bool)0)
20#define True ((Bool)1)
21
sewardjd465d992006-10-17 01:46:55 +000022void* walk_type_fn = NULL;
23
sewardj6ec98e82006-03-10 21:48:29 +000024static Ty tycon_Contiguous ( int count, Ty t )
25{
26 Ty t2;
27 int r = MPI_Type_contiguous( count, t, &t2 );
28 assert(r == MPI_SUCCESS);
29 return t2;
30}
31
32static Ty tycon_Struct2 ( int d1, int copies1, Ty t1,
33 int d2, int copies2, Ty t2 )
34{
35 int blocklens[2];
36 MPI_Aint disps[2];
37 Ty tys[2];
38 Ty tres;
39 int r;
40 blocklens[0] = copies1;
41 blocklens[1] = copies2;
42 disps[0] = d1;
43 disps[1] = d2;
44 tys[0] = t1;
45 tys[1] = t2;
46 r = MPI_Type_struct( 2, blocklens, disps, tys, &tres );
47 assert(r == MPI_SUCCESS);
48 return tres;
49}
50
51static Ty tycon_Vector ( int count, int blocklen, int stride, Ty t )
52{
53 Ty tres;
54 int r;
55 r = MPI_Type_vector( count, blocklen, stride, t, &tres );
56 assert(r == MPI_SUCCESS);
57 return tres;
58}
59
60static Ty tycon_HVector ( int count, int blocklen, MPI_Aint stride, Ty t )
61{
62 Ty tres;
63 int r;
64 r = MPI_Type_hvector( count, blocklen, stride, t, &tres );
65 assert(r == MPI_SUCCESS);
66 return tres;
67}
68
69static Ty tycon_Indexed2 ( int d1, int copies1,
70 int d2, int copies2, Ty t )
71{
72 int blocklens[2];
73 int disps[2];
74 Ty tres;
75 int r;
76 blocklens[0] = copies1;
77 blocklens[1] = copies2;
78 disps[0] = d1;
79 disps[1] = d2;
80 r = MPI_Type_indexed( 2, blocklens, disps, t, &tres );
81 assert(r == MPI_SUCCESS);
82 return tres;
83}
84
85static Ty tycon_HIndexed2 ( MPI_Aint d1, int copies1,
86 MPI_Aint d2, int copies2, Ty t )
87{
88 int blocklens[2];
89 MPI_Aint disps[2];
90 Ty tres;
91 int r;
92 blocklens[0] = copies1;
93 blocklens[1] = copies2;
94 disps[0] = d1;
95 disps[1] = d2;
96 r = MPI_Type_hindexed( 2, blocklens, disps, t, &tres );
97 assert(r == MPI_SUCCESS);
98 return tres;
99}
100
sewardjd465d992006-10-17 01:46:55 +0000101/* ------------------------------ */
sewardj6ec98e82006-03-10 21:48:29 +0000102
103char characterise ( unsigned char b )
104{
105 if (b == 0x00) return 'D';
106 if (b == 0xFF) return '.';
107 return '?';
108}
109
110void sendToMyself_callback( void* v, long n )
111{
112 long i;
113 unsigned char* p = (unsigned char*)v;
114 if (0) printf("callback: %p %ld\n", v, n);
115 for (i = 0; i < n; i++)
116 p[i] = 0x00;
117}
118
119void sendToMyself ( Bool commit_free, Ty* tyP, char* name )
120{
121 int i;
122 MPI_Aint lb, ub, ex;
123 MPI_Request req;
124 MPI_Status status;
125 char* sbuf;
126 char* rbuf;
127 char* rbuf_walk;
128 int r;
129
sewardj6ec98e82006-03-10 21:48:29 +0000130 /* C: what a fabulous functional programming language :-) */
sewardjd465d992006-10-17 01:46:55 +0000131 void(*dl_walk_type)(void(*)(void*,long),char*,MPI_Datatype)
132 = (void(*)(void(*)(void*,long),char*,MPI_Datatype))
133 walk_type_fn;
134
sewardj6ec98e82006-03-10 21:48:29 +0000135 if (!dl_walk_type) {
sewardj6f286c32007-03-29 16:35:00 +0000136 printf("sendToMyself: can't establish type walker fn\n");
sewardj6ec98e82006-03-10 21:48:29 +0000137 return;
138 }
139
140 printf("\nsendToMyself: trying %s\n", name);
141
142 if (commit_free) {
143 r = MPI_Type_commit( tyP );
144 assert(r == MPI_SUCCESS);
145 }
146
147 r = MPI_Type_lb( *tyP, &lb );
148 assert(r == MPI_SUCCESS);
149 r = MPI_Type_ub( *tyP, &ub );
150 assert(r == MPI_SUCCESS);
151 r = MPI_Type_extent( *tyP, &ex );
152 assert(r == MPI_SUCCESS);
153 printf("sendToMyself: ex=%d (%d,%d)\n", (int)ex, (int)lb, (int)ub);
154 assert(lb >= 0);
155
156 /* Fill send buffer with zeroes */
157 sbuf = malloc(ub);
158 assert(sbuf);
159 for (i = 0; i < ub; i++)
160 sbuf[i] = 0;
161
162 r = MPI_Isend( sbuf,1,*tyP, 0,99,MPI_COMM_WORLD, &req);
163 assert(r == MPI_SUCCESS);
164
165 /* Fill recv buffer with 0xFFs */
166 rbuf = malloc(ub);
167 assert(rbuf);
168 for (i = 0; i < ub; i++)
169 rbuf[i] = 0xFF;
170
171 r = MPI_Recv( rbuf,1,*tyP, 0,99,MPI_COMM_WORLD, &status);
172 assert(r == MPI_SUCCESS);
173
174 /* Now: rbuf should contain 0x00s where data was transferred and
175 undefined 0xFFs where data was not transferred. Get
176 libmpiwrap.so to walk the transferred type, using the callback
177 to set to 0x00 all parts of rbuf_walk it considers part of the
178 type. */
179
180 rbuf_walk = malloc(ub);
181 assert(rbuf_walk);
182 for (i = 0; i < ub; i++)
183 rbuf_walk[i] = 0xFF;
184
185 dl_walk_type( sendToMyself_callback, rbuf_walk, *tyP );
186
sewardj6ec98e82006-03-10 21:48:29 +0000187 if (commit_free) {
188 r = MPI_Type_free( tyP );
189 assert(r == MPI_SUCCESS);
190 }
191
192 for (i = 0; i < ub; i++) {
193 if (rbuf_walk[i] == rbuf[i])
194 continue; /* ok */
195 else
196 break; /* discrepancy */
197 }
198
199 if (i == ub)
200 printf("SUCCESS\n");
201 else
202 printf("FAILED\n");
203
sewardj896a7fd2007-06-05 19:51:02 +0000204 printf(" libmpiwrap=");
sewardj6ec98e82006-03-10 21:48:29 +0000205 for (i = 0; i < ub; i++)
206 printf("%c", characterise(rbuf_walk[i]));
207 printf("\n");
208
sewardj896a7fd2007-06-05 19:51:02 +0000209 printf("MPI library=");
sewardj6ec98e82006-03-10 21:48:29 +0000210 for (i = 0; i < ub; i++)
211 printf("%c", characterise(rbuf[i]));
212 printf("\n");
sewardjb4017222006-11-23 15:14:18 +0000213
214 free(sbuf);
215 free(rbuf);
216 free(rbuf_walk);
sewardj6ec98e82006-03-10 21:48:29 +0000217}
218
219
220typedef char* Nm;
221
222int main ( int argc, char** argv )
223{
224 int rank, size;
sewardjd465d992006-10-17 01:46:55 +0000225 char* opts;
sewardj6ec98e82006-03-10 21:48:29 +0000226
227 if (!RUNNING_ON_VALGRIND) {
228 printf("error: this program must be run on valgrind\n");
229 return 1;
230 }
sewardjd465d992006-10-17 01:46:55 +0000231 opts = getenv("MPIWRAP_DEBUG");
232 if ((!opts) || NULL==strstr(opts, "initkludge")) {
233 printf("error: program requires MPIWRAP_DEBUG=initkludge\n");
234 return 1;
235 }
sewardj6ec98e82006-03-10 21:48:29 +0000236
sewardj6f286c32007-03-29 16:35:00 +0000237 /* Note: this trick doesn't work on 64-bit platforms,
238 since MPI_Init returns int. */
sewardjd465d992006-10-17 01:46:55 +0000239 walk_type_fn = (void*)(long) MPI_Init( &argc, &argv );
240 printf("mpiwrap_type_test: walk_type_fn = %p\n", walk_type_fn);
241 assert(walk_type_fn);
242
sewardj6ec98e82006-03-10 21:48:29 +0000243 MPI_Comm_size( MPI_COMM_WORLD, &size );
244 MPI_Comm_rank( MPI_COMM_WORLD, &rank );
245
246 if (rank == 0) {
247
sewardj896a7fd2007-06-05 19:51:02 +0000248#define TRY(_commit_free,_type,_name) \
249 do { Ty ty = (_type); \
250 Nm nm = (_name); \
251 sendToMyself((_commit_free), &ty, nm); \
252 } while (0)
sewardj6ec98e82006-03-10 21:48:29 +0000253
sewardj896a7fd2007-06-05 19:51:02 +0000254 TRY(True, tycon_Contiguous(3, MPI_INT),
255 "Contig{3xINT}");
sewardj6ec98e82006-03-10 21:48:29 +0000256
sewardj896a7fd2007-06-05 19:51:02 +0000257 TRY(True, tycon_Struct2(3,2,MPI_CHAR, 8,1,MPI_DOUBLE),
258 "Struct{h3:2xCHAR, h8:1xDOUBLE}");
sewardj6ec98e82006-03-10 21:48:29 +0000259
sewardj896a7fd2007-06-05 19:51:02 +0000260 TRY(True, tycon_Struct2(0,1,MPI_CHAR, 8,1,tycon_Contiguous(4, MPI_DOUBLE)),
261 "Struct{h0:1xCHAR, h8:1xContig{4xDOUBLE}}");
sewardj6ec98e82006-03-10 21:48:29 +0000262
sewardj896a7fd2007-06-05 19:51:02 +0000263 TRY(True, tycon_Contiguous(10, tycon_Struct2(1,1,MPI_CHAR, 4,1,MPI_FLOAT)),
264 "Contig{10xStruct{h1:1xCHAR, h4:1xFLOAT}}");
sewardj6ec98e82006-03-10 21:48:29 +0000265
sewardj896a7fd2007-06-05 19:51:02 +0000266 TRY(True, tycon_Vector(5, 2,3,MPI_DOUBLE),
267 "Vector{5x(2,3)xDOUBLE}");
sewardj6ec98e82006-03-10 21:48:29 +0000268
sewardj896a7fd2007-06-05 19:51:02 +0000269 TRY(True, tycon_Vector(3, 1,2,MPI_LONG_DOUBLE),
270 "Vector{3x(1,2)xLONG_DOUBLE}");
sewardj6ec98e82006-03-10 21:48:29 +0000271
sewardj896a7fd2007-06-05 19:51:02 +0000272 TRY(True, tycon_HVector(4, 1,3,MPI_SHORT),
273 "HVector{4x(1,h3)xSHORT}");
sewardj6ec98e82006-03-10 21:48:29 +0000274
sewardj896a7fd2007-06-05 19:51:02 +0000275 TRY(True, tycon_Indexed2(1,3, 5,2, MPI_UNSIGNED_CHAR),
276 "Indexed{1:3x,5:2x,UNSIGNED_CHAR}");
sewardj6ec98e82006-03-10 21:48:29 +0000277
sewardj896a7fd2007-06-05 19:51:02 +0000278 TRY(True, tycon_HIndexed2(1,2, 6,3, MPI_UNSIGNED_SHORT),
279 "HIndexed{h1:2x,h6:3x,UNSIGNED_SHORT}");
sewardj6ec98e82006-03-10 21:48:29 +0000280
sewardj896a7fd2007-06-05 19:51:02 +0000281 TRY(False, MPI_FLOAT_INT, "FLOAT_INT");
282 TRY(False, MPI_DOUBLE_INT, "DOUBLE_INT");
283 TRY(False, MPI_LONG_INT, "LONG_INT");
284 TRY(False, MPI_SHORT_INT, "SHORT_INT");
285 TRY(False, MPI_2INT, "2INT");
286 TRY(False, MPI_LONG_DOUBLE_INT, "LONG_DOUBLE_INT");
sewardj6ec98e82006-03-10 21:48:29 +0000287
sewardj896a7fd2007-06-05 19:51:02 +0000288 /* The next 4 don't seem to exist on openmpi-1.2.2. */
sewardj6ec98e82006-03-10 21:48:29 +0000289
sewardj896a7fd2007-06-05 19:51:02 +0000290#if defined(MPI_REAL8)
291 TRY(False, MPI_REAL8, "REAL8");
292#endif
293#if defined(MPI_REAL4)
294 TRY(False, MPI_REAL4, "REAL4");
295#endif
296#if defined(MPI_INTEGER8)
297 TRY(False, MPI_INTEGER8, "INTEGER8");
298#endif
299#if defined(MPI_INTEGER4)
300 TRY(False, MPI_INTEGER4, "INTEGER4");
301#endif
sewardj6ec98e82006-03-10 21:48:29 +0000302
sewardj896a7fd2007-06-05 19:51:02 +0000303 TRY(False, MPI_COMPLEX, "COMPLEX");
304 TRY(False, MPI_DOUBLE_COMPLEX, "DOUBLE_COMPLEX");
sewardj6f286c32007-03-29 16:35:00 +0000305
sewardj896a7fd2007-06-05 19:51:02 +0000306 // On openmpi-1.2.2 on x86-linux, sendToMyself bombs openmpi,
307 // for some reason (openmpi thinks these all have zero size/extent
308 // and therefore can't be MPI_Send-ed, AIUI).
309 // TRY(False, MPI_LOGICAL, "LOGICAL");
310 // TRY(False, MPI_REAL, "REAL");
311 // TRY(False, MPI_DOUBLE_PRECISION, "DOUBLE_PRECISION");
312 // TRY(False, MPI_INTEGER, "INTEGER");
313 TRY(False, MPI_2INTEGER, "2INTEGER");
314 TRY(False, MPI_2COMPLEX, "2COMPLEX");
315 TRY(False, MPI_2DOUBLE_COMPLEX, "2DOUBLE_COMPLEX");
316 TRY(False, MPI_2REAL, "2REAL");
317 TRY(False, MPI_2DOUBLE_PRECISION, "2DOUBLE_PRECISION");
318 TRY(False, MPI_CHARACTER, "CHARACTER");
sewardj6f286c32007-03-29 16:35:00 +0000319
sewardj896a7fd2007-06-05 19:51:02 +0000320 /* The following from a table in chapter 9 of the MPI2 spec
321 date Nov 15, 2003, page 247. */
322 TRY(False, MPI_PACKED, "PACKED");
323 TRY(False, MPI_BYTE, "BYTE");
324 TRY(False, MPI_CHAR, "CHAR");
325 TRY(False, MPI_UNSIGNED_CHAR, "UNSIGNED_CHAR");
326 TRY(False, MPI_SIGNED_CHAR, "SIGNED_CHAR");
327 TRY(False, MPI_WCHAR, "WCHAR");
328 TRY(False, MPI_SHORT, "SHORT");
329 TRY(False, MPI_UNSIGNED_SHORT, "UNSIGNED_SHORT");
330 TRY(False, MPI_INT, "INT");
331 TRY(False, MPI_UNSIGNED, "UNSIGNED");
332 TRY(False, MPI_LONG, "LONG");
333 TRY(False, MPI_UNSIGNED_LONG, "UNSIGNED_LONG");
334 TRY(False, MPI_FLOAT, "FLOAT");
335 TRY(False, MPI_DOUBLE, "DOUBLE");
336 TRY(False, MPI_LONG_DOUBLE, "LONG_DOUBLE");
337 TRY(False, MPI_CHARACTER, "CHARACTER");
sewardj6f286c32007-03-29 16:35:00 +0000338
sewardj896a7fd2007-06-05 19:51:02 +0000339 // Same deal as above
340 // TRY(False, MPI_LOGICAL, "LOGICAL");
341 // TRY(False, MPI_INTEGER, "INTEGER");
342 // TRY(False, MPI_REAL, "REAL");
343 // TRY(False, MPI_DOUBLE_PRECISION, "DOUBLE_PRECISION");
sewardj6f286c32007-03-29 16:35:00 +0000344
sewardj896a7fd2007-06-05 19:51:02 +0000345 TRY(False, MPI_COMPLEX, "COMPLEX");
346 TRY(False, MPI_DOUBLE_COMPLEX, "DOUBLE_COMPLEX");
347#if defined(MPI_INTEGER1)
348 TRY(False, MPI_INTEGER1, "INTEGER1");
349#endif
350#if defined(MPI_INTEGER2)
351 TRY(False, MPI_INTEGER2, "INTEGER2");
352#endif
353#if defined(MPI_INTEGER4)
354 TRY(False, MPI_INTEGER4, "INTEGER4");
355#endif
356#if defined(MPI_INTEGER8)
357 TRY(False, MPI_INTEGER8, "INTEGER8");
358#endif
359 TRY(False, MPI_LONG_LONG, "LONG_LONG");
360 TRY(False, MPI_UNSIGNED_LONG_LONG, "UNSIGNED_LONG_LONG");
361#if defined(MPI_REAL4)
362 TRY(False, MPI_REAL4, "REAL4");
363#endif
364#if defined(MPI_REAL8)
365 TRY(False, MPI_REAL8, "REAL8");
366#endif
367#if defined(MPI_REAL16)
368 TRY(False, MPI_REAL16, "REAL16");
369#endif
sewardj6f286c32007-03-29 16:35:00 +0000370
sewardj896a7fd2007-06-05 19:51:02 +0000371#undef TRY
372
sewardj6ec98e82006-03-10 21:48:29 +0000373 }
374
375 MPI_Finalize();
376 return 0;
377}