blob: 1b1c9f46764ede99062b40bea7382827e34a63ea [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
204 for (i = 0; i < ub; i++)
205 printf("%c", characterise(rbuf_walk[i]));
206 printf("\n");
207
208 for (i = 0; i < ub; i++)
209 printf("%c", characterise(rbuf[i]));
210 printf("\n");
sewardjb4017222006-11-23 15:14:18 +0000211
212 free(sbuf);
213 free(rbuf);
214 free(rbuf_walk);
sewardj6ec98e82006-03-10 21:48:29 +0000215}
216
217
218typedef char* Nm;
219
220int main ( int argc, char** argv )
221{
222 int rank, size;
sewardjd465d992006-10-17 01:46:55 +0000223 char* opts;
sewardj6ec98e82006-03-10 21:48:29 +0000224
225 if (!RUNNING_ON_VALGRIND) {
226 printf("error: this program must be run on valgrind\n");
227 return 1;
228 }
sewardjd465d992006-10-17 01:46:55 +0000229 opts = getenv("MPIWRAP_DEBUG");
230 if ((!opts) || NULL==strstr(opts, "initkludge")) {
231 printf("error: program requires MPIWRAP_DEBUG=initkludge\n");
232 return 1;
233 }
sewardj6ec98e82006-03-10 21:48:29 +0000234
sewardj6f286c32007-03-29 16:35:00 +0000235 /* Note: this trick doesn't work on 64-bit platforms,
236 since MPI_Init returns int. */
sewardjd465d992006-10-17 01:46:55 +0000237 walk_type_fn = (void*)(long) MPI_Init( &argc, &argv );
238 printf("mpiwrap_type_test: walk_type_fn = %p\n", walk_type_fn);
239 assert(walk_type_fn);
240
sewardj6ec98e82006-03-10 21:48:29 +0000241 MPI_Comm_size( MPI_COMM_WORLD, &size );
242 MPI_Comm_rank( MPI_COMM_WORLD, &rank );
243
244 if (rank == 0) {
245
sewardj6f286c32007-03-29 16:35:00 +0000246 Ty t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18;
247 Nm n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18;
sewardj6ec98e82006-03-10 21:48:29 +0000248
249 t2 = tycon_Contiguous(3, MPI_INT);
250 n2 = "Contig{3xINT}";
251
252 t3 = tycon_Struct2(3,2,MPI_CHAR, 8,1,MPI_DOUBLE);
253 n3 = "Struct{h3:2xCHAR, h8:1xDOUBLE}";
254
255 t4 = tycon_Struct2(0,1,MPI_CHAR, 8,1,tycon_Contiguous(4, MPI_DOUBLE));
256 n4 = "Struct{h0:1xCHAR, h8:1xContig{4xDOUBLE}}";
257
258 t5 = tycon_Contiguous(10, tycon_Struct2(1,1,MPI_CHAR, 4,1,MPI_FLOAT));
259 n5 = "Contig{10xStruct{h1:1xCHAR, h4:1xFLOAT}}";
260
261 t6 = tycon_Vector(5, 2,3,MPI_DOUBLE);
262 n6 = "Vector{5x(2,3)xDOUBLE}";
263
264 t7 = tycon_Vector(3, 1,2,MPI_LONG_DOUBLE);
265 n7 = "Vector{3x(1,2)xLONG_DOUBLE}";
266
267 t8 = tycon_HVector(4, 1,3,MPI_SHORT);
268 n8 = "HVector{4x(1,h3)xSHORT}";
269
270 t9 = tycon_Indexed2(1,3, 5,2, MPI_UNSIGNED_CHAR);
271 n9 = "Indexed{1:3x,5:2x,UNSIGNED_CHAR}";
272
273 t10 = tycon_HIndexed2(1,2, 6,3, MPI_UNSIGNED_SHORT);
274 n10 = "HIndexed{h1:2x,h6:3x,UNSIGNED_SHORT}";
275
276 t11 = MPI_LONG_INT;
277 n11 = "LONG_INT";
278
279 t12 = MPI_DOUBLE_INT;
280 n12 = "DOUBLE_INT";
281
282 t13 = MPI_SHORT_INT;
283 n13 = "SHORT_INT";
284
sewardj6f286c32007-03-29 16:35:00 +0000285 t14 = MPI_REAL8;
286 n14 = "REAL8";
287
288 t15 = MPI_REAL4;
289 n15 = "REAL4";
290
291 t16 = MPI_INTEGER8;
292 n16 = "INTEGER8";
293
294 t17 = MPI_INTEGER4;
295 n17 = "INTEGER4";
296
297 t18 = MPI_2INT;
298 n18 = "2INT";
299
sewardj6ec98e82006-03-10 21:48:29 +0000300 sendToMyself(True, &t2, n2);
301 sendToMyself(True, &t3, n3);
302 sendToMyself(True, &t4, n4);
303 sendToMyself(True, &t5, n5);
304 sendToMyself(True, &t6, n6);
305 sendToMyself(True, &t7, n7);
306 sendToMyself(True, &t8, n8);
307 sendToMyself(True, &t9, n9);
308 sendToMyself(True, &t10, n10);
309 sendToMyself(False, &t11, n11);
310 sendToMyself(False, &t12, n12);
311 sendToMyself(False, &t13, n13);
sewardj6f286c32007-03-29 16:35:00 +0000312 sendToMyself(False, &t14, n14);
313 sendToMyself(False, &t15, n15);
314 sendToMyself(False, &t16, n16);
315 sendToMyself(False, &t17, n17);
316 sendToMyself(False, &t18, n18);
sewardj6ec98e82006-03-10 21:48:29 +0000317 }
318
319 MPI_Finalize();
320 return 0;
321}