Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Reduce the size of partial shared malloc tests.
[simgrid.git] / teshsuite / smpi / mpich3-test / datatype / unusual-noncontigs.c
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  *  (C) 2001 by Argonne National Laboratory.
4  *      See COPYRIGHT in top-level directory.
5  */
6 #include <math.h>
7 #include <assert.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include "mpi.h"
12
13 /*
14    The default behavior of the test routines should be to briefly indicate
15    the cause of any errors - in this test, that means that verbose needs
16    to be set. Verbose should turn on output that is independent of error
17    levels.
18 */
19 static int verbose = 1;
20
21 int main(int argc, char *argv[]);
22 int parse_args(int argc, char **argv);
23 int struct_negdisp_test(void);
24 int vector_negstride_test(void);
25 int indexed_negdisp_test(void);
26 int struct_struct_test(void);
27 int flatten_test(void);
28
29 int build_array_section_type(MPI_Aint aext, MPI_Aint astart, MPI_Aint aend,
30                              MPI_Datatype * datatype);
31
32 int main(int argc, char *argv[])
33 {
34     int err, errs = 0;
35
36     /* Initialize MPI */
37     MPI_Init(&argc, &argv);
38     parse_args(argc, argv);
39
40     /* To improve reporting of problems about operations, we
41      * change the error handler to errors return */
42     MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
43
44     err = struct_negdisp_test();
45     if (verbose && err)
46         fprintf(stderr, "error in struct_negdisp_test\n");
47     errs += err;
48
49     err = vector_negstride_test();
50     if (verbose && err)
51         fprintf(stderr, "error in vector_negstride_test\n");
52     errs += err;
53
54     err = indexed_negdisp_test();
55     if (verbose && err)
56         fprintf(stderr, "error in indexed_negdisp_test\n");
57     errs += err;
58
59     err = struct_struct_test();
60     if (verbose && err)
61         fprintf(stderr, "error in struct_struct_test\n");
62     errs += err;
63
64     err = flatten_test();
65     if (verbose && err)
66         fprintf(stderr, "error in flatten_test\n");
67     errs += err;
68
69     /* print message and exit */
70     if (errs) {
71         fprintf(stderr, "Found %d errors\n", errs);
72     }
73     else {
74         printf(" No Errors\n");
75     }
76     MPI_Finalize();
77     return 0;
78 }
79
80 /* test uses a struct type that describes data that is contiguous,
81  * but processed in a noncontiguous way.
82  */
83 int struct_negdisp_test(void)
84 {
85     int err, errs = 0;
86     int sendbuf[6] = { 1, 2, 3, 4, 5, 6 };
87     int recvbuf[6] = { -1, -2, -3, -4, -5, -6 };
88     MPI_Datatype mystruct;
89     MPI_Request request;
90     MPI_Status status;
91
92     MPI_Aint disps[2] = { 0, -1 * ((int) sizeof(int)) };
93     int blks[2] = { 1, 1, };
94     MPI_Datatype types[2] = { MPI_INT, MPI_INT };
95
96     err = MPI_Type_struct(2, blks, disps, types, &mystruct);
97     if (err != MPI_SUCCESS) {
98         errs++;
99         if (verbose) {
100             fprintf(stderr, "MPI_Type_struct returned error\n");
101         }
102     }
103
104     MPI_Type_commit(&mystruct);
105
106     err = MPI_Irecv(recvbuf + 1, 4, MPI_INT, 0, 0, MPI_COMM_SELF, &request);
107     if (err != MPI_SUCCESS) {
108         errs++;
109         if (verbose) {
110             fprintf(stderr, "MPI_Irecv returned error\n");
111         }
112     }
113
114     err = MPI_Send(sendbuf + 2, 2, mystruct, 0, 0, MPI_COMM_SELF);
115     if (err != MPI_SUCCESS) {
116         errs++;
117         if (verbose) {
118             fprintf(stderr, "MPI_Send returned error\n");
119         }
120     }
121
122     err = MPI_Wait(&request, &status);
123     if (err != MPI_SUCCESS) {
124         errs++;
125         if (verbose) {
126             fprintf(stderr, "MPI_Wait returned error\n");
127         }
128     }
129
130     /* verify data */
131     if (recvbuf[0] != -1) {
132         errs++;
133         if (verbose) {
134             fprintf(stderr, "recvbuf[0] = %d; should be %d\n", recvbuf[0], -1);
135         }
136     }
137     if (recvbuf[1] != 3) {
138         errs++;
139         if (verbose) {
140             fprintf(stderr, "recvbuf[1] = %d; should be %d\n", recvbuf[1], 3);
141         }
142     }
143     if (recvbuf[2] != 2) {
144         errs++;
145         if (verbose) {
146             fprintf(stderr, "recvbuf[2] = %d; should be %d\n", recvbuf[2], 2);
147         }
148     }
149     if (recvbuf[3] != 5) {
150         errs++;
151         if (verbose) {
152             fprintf(stderr, "recvbuf[3] = %d; should be %d\n", recvbuf[3], 5);
153         }
154     }
155     if (recvbuf[4] != 4) {
156         errs++;
157         if (verbose) {
158             fprintf(stderr, "recvbuf[4] = %d; should be %d\n", recvbuf[4], 4);
159         }
160     }
161     if (recvbuf[5] != -6) {
162         errs++;
163         if (verbose) {
164             fprintf(stderr, "recvbuf[5] = %d; should be %d\n", recvbuf[5], -6);
165         }
166     }
167
168     MPI_Type_free(&mystruct);
169
170     return errs;
171 }
172
173 /* test uses a vector type that describes data that is contiguous,
174  * but processed in a noncontiguous way.  this is effectively the
175  * same type as in the struct_negdisp_test above.
176  */
177 int vector_negstride_test(void)
178 {
179     int err, errs = 0;
180     int sendbuf[6] = { 1, 2, 3, 4, 5, 6 };
181     int recvbuf[6] = { -1, -2, -3, -4, -5, -6 };
182     MPI_Datatype myvector;
183     MPI_Request request;
184     MPI_Status status;
185
186     err = MPI_Type_vector(2, 1, -1, MPI_INT, &myvector);
187     if (err != MPI_SUCCESS) {
188         errs++;
189         if (verbose) {
190             fprintf(stderr, "MPI_Type_vector returned error\n");
191         }
192     }
193
194     MPI_Type_commit(&myvector);
195
196     err = MPI_Irecv(recvbuf + 1, 4, MPI_INT, 0, 0, MPI_COMM_SELF, &request);
197     if (err != MPI_SUCCESS) {
198         errs++;
199         if (verbose) {
200             fprintf(stderr, "MPI_Irecv returned error\n");
201         }
202     }
203
204     err = MPI_Send(sendbuf + 2, 2, myvector, 0, 0, MPI_COMM_SELF);
205     if (err != MPI_SUCCESS) {
206         errs++;
207         if (verbose) {
208             fprintf(stderr, "MPI_Send returned error\n");
209         }
210     }
211
212     err = MPI_Wait(&request, &status);
213     if (err != MPI_SUCCESS) {
214         errs++;
215         if (verbose) {
216             fprintf(stderr, "MPI_Wait returned error\n");
217         }
218     }
219
220     /* verify data */
221     if (recvbuf[0] != -1) {
222         errs++;
223         if (verbose) {
224             fprintf(stderr, "recvbuf[0] = %d; should be %d\n", recvbuf[0], -1);
225         }
226     }
227     if (recvbuf[1] != 3) {
228         errs++;
229         if (verbose) {
230             fprintf(stderr, "recvbuf[1] = %d; should be %d\n", recvbuf[1], 3);
231         }
232     }
233     if (recvbuf[2] != 2) {
234         errs++;
235         if (verbose) {
236             fprintf(stderr, "recvbuf[2] = %d; should be %d\n", recvbuf[2], 2);
237         }
238     }
239     if (recvbuf[3] != 5) {
240         errs++;
241         if (verbose) {
242             fprintf(stderr, "recvbuf[3] = %d; should be %d\n", recvbuf[3], 5);
243         }
244     }
245     if (recvbuf[4] != 4) {
246         errs++;
247         if (verbose) {
248             fprintf(stderr, "recvbuf[4] = %d; should be %d\n", recvbuf[4], 4);
249         }
250     }
251     if (recvbuf[5] != -6) {
252         errs++;
253         if (verbose) {
254             fprintf(stderr, "recvbuf[5] = %d; should be %d\n", recvbuf[5], -6);
255         }
256     }
257
258     MPI_Type_free(&myvector);
259
260     return errs;
261 }
262
263 /* test uses a indexed type that describes data that is contiguous,
264  * but processed in a noncontiguous way.  this is effectively the same
265  * type as in the two tests above.
266  */
267 int indexed_negdisp_test(void)
268 {
269     int err, errs = 0;
270     int sendbuf[6] = { 1, 2, 3, 4, 5, 6 };
271     int recvbuf[6] = { -1, -2, -3, -4, -5, -6 };
272     MPI_Datatype myindexed;
273     MPI_Request request;
274     MPI_Status status;
275
276     int disps[2] = { 0, -1 };
277     int blks[2] = { 1, 1 };
278
279     err = MPI_Type_indexed(2, blks, disps, MPI_INT, &myindexed);
280     if (err != MPI_SUCCESS) {
281         errs++;
282         if (verbose) {
283             fprintf(stderr, "MPI_Type_indexed returned error\n");
284         }
285     }
286
287     MPI_Type_commit(&myindexed);
288
289     err = MPI_Irecv(recvbuf + 1, 4, MPI_INT, 0, 0, MPI_COMM_SELF, &request);
290     if (err != MPI_SUCCESS) {
291         errs++;
292         if (verbose) {
293             fprintf(stderr, "MPI_Irecv returned error\n");
294         }
295     }
296
297     err = MPI_Send(sendbuf + 2, 2, myindexed, 0, 0, MPI_COMM_SELF);
298     if (err != MPI_SUCCESS) {
299         errs++;
300         if (verbose) {
301             fprintf(stderr, "MPI_Send returned error\n");
302         }
303     }
304
305     err = MPI_Wait(&request, &status);
306     if (err != MPI_SUCCESS) {
307         errs++;
308         if (verbose) {
309             fprintf(stderr, "MPI_Wait returned error\n");
310         }
311     }
312
313     /* verify data */
314     if (recvbuf[0] != -1) {
315         errs++;
316         if (verbose) {
317             fprintf(stderr, "recvbuf[0] = %d; should be %d\n", recvbuf[0], -1);
318         }
319     }
320     if (recvbuf[1] != 3) {
321         errs++;
322         if (verbose) {
323             fprintf(stderr, "recvbuf[1] = %d; should be %d\n", recvbuf[1], 3);
324         }
325     }
326     if (recvbuf[2] != 2) {
327         errs++;
328         if (verbose) {
329             fprintf(stderr, "recvbuf[2] = %d; should be %d\n", recvbuf[2], 2);
330         }
331     }
332     if (recvbuf[3] != 5) {
333         errs++;
334         if (verbose) {
335             fprintf(stderr, "recvbuf[3] = %d; should be %d\n", recvbuf[3], 5);
336         }
337     }
338     if (recvbuf[4] != 4) {
339         errs++;
340         if (verbose) {
341             fprintf(stderr, "recvbuf[4] = %d; should be %d\n", recvbuf[4], 4);
342         }
343     }
344     if (recvbuf[5] != -6) {
345         errs++;
346         if (verbose) {
347             fprintf(stderr, "recvbuf[5] = %d; should be %d\n", recvbuf[5], -6);
348         }
349     }
350
351     MPI_Type_free(&myindexed);
352
353     return errs;
354 }
355
356 #define check_err(fn_name_)                                                   \
357     do {                                                                      \
358         if (err != MPI_SUCCESS) {                                             \
359             errs++;                                                           \
360             if (verbose) {                                                    \
361                 int len_;                                                     \
362                 char err_str_[MPI_MAX_ERROR_STRING];                          \
363                 MPI_Error_string(err, err_str_, &len_);                       \
364                 fprintf(stderr, #fn_name_ " failed at line %d, err=%d: %s\n", \
365                         __LINE__, err, err_str_);                             \
366             }                                                                 \
367         }                                                                     \
368     } while (0)
369 /* test case from tt#1030 ported to C
370  *
371  * Thanks to Matthias Lieber for reporting the bug and providing a good test
372  * program. */
373 int struct_struct_test(void)
374 {
375     int err, errs = 0;
376     int i, j, dt_size = 0;
377     MPI_Request req[2];
378
379
380 #define COUNT (2)
381     MPI_Aint displ[COUNT];
382     int blens[COUNT];
383     MPI_Datatype types[COUNT];
384     MPI_Datatype datatype;
385
386     /* A slight difference from the F90 test: F90 arrays are column-major, C
387      * arrays are row-major.  So we invert the order of dimensions. */
388 #define N (2)
389 #define M (4)
390     int array[N][M] = { {-1, -1, -1, -1}, {-1, -1, -1, -1} };
391     int expected[N][M] = { {-1, 1, 2, 5}, {-1, 3, 4, 6} };
392     int seq_array[N * M];
393     MPI_Aint astart, aend;
394     MPI_Aint size_exp = 0;
395
396     /* 1st section selects elements 1 and 2 out of 2nd dimension, complete 1st dim.
397      * should receive the values 1, 2, 3, 4 */
398     astart = 1;
399     aend = 2;
400     err = build_array_section_type(M, astart, aend, &types[0]);
401     if (err) {
402         errs++;
403         if (verbose)
404             fprintf(stderr, "build_array_section_type failed\n");
405         return errs;
406     }
407     blens[0] = N;
408     displ[0] = 0;
409     size_exp = size_exp + N * (aend - astart + 1) * sizeof(int);
410
411     /* 2nd section selects last element of 2nd dimension, complete 1st dim.
412      * should receive the values 5, 6 */
413     astart = 3;
414     aend = 3;
415     err = build_array_section_type(M, astart, aend, &types[1]);
416     if (err) {
417         errs++;
418         if (verbose)
419             fprintf(stderr, "build_array_section_type failed\n");
420         return errs;
421     }
422     blens[1] = N;
423     displ[1] = 0;
424     size_exp = size_exp + N * (aend - astart + 1) * sizeof(int);
425
426     /* create type */
427     err = MPI_Type_create_struct(COUNT, blens, displ, types, &datatype);
428     check_err(MPI_Type_create_struct);
429     err = MPI_Type_commit(&datatype);
430     check_err(MPI_Type_commit);
431
432     err = MPI_Type_size(datatype, &dt_size);
433     check_err(MPI_Type_size);
434     if (dt_size != size_exp) {
435         errs++;
436         if (verbose)
437             fprintf(stderr, "unexpected type size\n");
438     }
439
440
441     /* send the type to ourselves to make sure that the type describes data correctly */
442     for (i = 0; i < (N * M); ++i)
443         seq_array[i] = i + 1;   /* source values 1..(N*M) */
444     err = MPI_Isend(&seq_array[0], dt_size / sizeof(int), MPI_INT, 0, 42, MPI_COMM_SELF, &req[0]);
445     check_err(MPI_Isend);
446     err = MPI_Irecv(&array[0][0], 1, datatype, 0, 42, MPI_COMM_SELF, &req[1]);
447     check_err(MPI_Irecv);
448     err = MPI_Waitall(2, req, MPI_STATUSES_IGNORE);
449     check_err(MPI_Waitall);
450
451     /* check against expected */
452     for (i = 0; i < N; ++i) {
453         for (j = 0; j < M; ++j) {
454             if (array[i][j] != expected[i][j]) {
455                 errs++;
456                 if (verbose)
457                     fprintf(stderr, "array[%d][%d]=%d, should be %d\n", i, j, array[i][j],
458                             expected[i][j]);
459             }
460         }
461     }
462
463     err = MPI_Type_free(&datatype);
464     check_err(MPI_Type_free);
465     err = MPI_Type_free(&types[0]);
466     check_err(MPI_Type_free);
467     err = MPI_Type_free(&types[1]);
468     check_err(MPI_Type_free);
469
470     return errs;
471 #undef M
472 #undef N
473 #undef COUNT
474 }
475
476 /*   create a datatype for a 1D int array subsection
477
478      - a subsection of the first dimension is defined via astart, aend
479      - indexes are assumed to start with 0, that means:
480        - 0 <= astart <= aend < aext
481      - astart and aend are inclusive
482
483      example:
484
485      aext = 8, astart=2, aend=4 would produce:
486
487      index     | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
488      1D array   ###############################
489      datatype   LB      ###########             UB
490  */
491 int build_array_section_type(MPI_Aint aext, MPI_Aint astart, MPI_Aint aend, MPI_Datatype * datatype)
492 {
493 #define COUNT (3)
494     int err, errs = 0;
495     MPI_Aint displ[COUNT];
496     int blens[COUNT];
497     MPI_Datatype types[COUNT];
498
499     *datatype = MPI_DATATYPE_NULL;
500
501     /* lower bound marker */
502     types[0] = MPI_LB;
503     displ[0] = 0;
504     blens[0] = 1;
505
506     /* subsection starting at astart */
507     displ[1] = astart * sizeof(int);
508     types[1] = MPI_INT;
509     blens[1] = aend - astart + 1;
510
511     /* upper bound marker */
512     types[2] = MPI_UB;
513     displ[2] = aext * sizeof(int);
514     blens[2] = 1;
515
516     err = MPI_Type_create_struct(COUNT, blens, displ, types, datatype);
517     if (err != MPI_SUCCESS) {
518         errs++;
519         if (verbose) {
520             fprintf(stderr, "MPI_Type_create_struct failed, err=%d\n", err);
521         }
522     }
523
524     return errs;
525 #undef COUNT
526 }
527
528 /* start_idx is the "zero" point for the unpack */
529 static int pack_and_check_expected(MPI_Datatype type, const char *name,
530                                    int start_idx, int size, int *array, int *expected)
531 {
532     int i;
533     int err, errs = 0;
534     int pack_size = -1;
535     int *pack_buf = NULL;
536     int pos;
537     int type_size = -1;
538     int sendbuf[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
539
540     err = MPI_Type_size(type, &type_size);
541     check_err(MPI_Type_size);
542     assert(sizeof(sendbuf) >= type_size);
543
544     err = MPI_Pack_size(type_size / sizeof(int), MPI_INT, MPI_COMM_SELF, &pack_size);
545     check_err(MPI_Pack_size);
546     pack_buf = malloc(pack_size);
547     assert(pack_buf);
548
549     pos = 0;
550     err =
551         MPI_Pack(&sendbuf[0], type_size / sizeof(int), MPI_INT, pack_buf, pack_size, &pos,
552                  MPI_COMM_SELF);
553     check_err(MPI_Pack);
554     pos = 0;
555     err = MPI_Unpack(pack_buf, pack_size, &pos, &array[start_idx], 1, type, MPI_COMM_SELF);
556     check_err(MPI_Unpack);
557     free(pack_buf);
558
559     /* check against expected */
560     for (i = 0; i < size; ++i) {
561         if (array[i] != expected[i]) {
562             errs++;
563             if (verbose)
564                 fprintf(stderr, "%s: array[%d]=%d, should be %d\n", name, i, array[i], expected[i]);
565         }
566     }
567
568     return errs;
569 }
570
571 /* regression for tt#1030, checks for bad offset math in the
572  * blockindexed and indexed dataloop flattening code */
573 int flatten_test(void)
574 {
575     int err, errs = 0;
576 #define ARR_SIZE (9)
577     /* real indices              0  1  2  3  4  5  6  7  8
578      * indices w/ &array[3]     -3 -2 -1  0  1  2  3  4  5 */
579     int array[ARR_SIZE] = { -1, -1, -1, -1, -1, -1, -1, -1, -1 };
580     int expected[ARR_SIZE] = { -1, 0, 1, -1, 2, -1, 3, -1, 4 };
581     MPI_Datatype idx_type = MPI_DATATYPE_NULL;
582     MPI_Datatype blkidx_type = MPI_DATATYPE_NULL;
583     MPI_Datatype combo = MPI_DATATYPE_NULL;
584 #define COUNT (2)
585     int displ[COUNT];
586     MPI_Aint adispl[COUNT];
587     int blens[COUNT];
588     MPI_Datatype types[COUNT];
589
590     /* indexed type layout:
591      * XX_X
592      * 2101  <-- pos (left of 0 is neg)
593      *
594      * different blens to prevent optimization into a blockindexed
595      */
596     blens[0] = 2;
597     displ[0] = -2;      /* elements, puts byte after block end at 0 */
598     blens[1] = 1;
599     displ[1] = 1;       /*elements */
600
601     err = MPI_Type_indexed(COUNT, blens, displ, MPI_INT, &idx_type);
602     check_err(MPI_Type_indexed);
603     err = MPI_Type_commit(&idx_type);
604     check_err(MPI_Type_commit);
605
606     /* indexed type layout:
607      * _X_X
608      * 2101  <-- pos (left of 0 is neg)
609      */
610     displ[0] = -1;
611     displ[1] = 1;
612     err = MPI_Type_create_indexed_block(COUNT, 1, displ, MPI_INT, &blkidx_type);
613     check_err(MPI_Type_indexed_block);
614     err = MPI_Type_commit(&blkidx_type);
615     check_err(MPI_Type_commit);
616
617     /* struct type layout:
618      * II_I_B_B  (I=idx_type, B=blkidx_type)
619      * 21012345  <-- pos (left of 0 is neg)
620      */
621     blens[0] = 1;
622     adispl[0] = 0;      /*bytes */
623     types[0] = idx_type;
624
625     blens[1] = 1;
626     adispl[1] = 4 * sizeof(int);        /* bytes */
627     types[1] = blkidx_type;
628
629     /* must be a struct in order to trigger flattening code */
630     err = MPI_Type_create_struct(COUNT, blens, adispl, types, &combo);
631     check_err(MPI_Type_indexed);
632     err = MPI_Type_commit(&combo);
633     check_err(MPI_Type_commit);
634
635     /* pack/unpack with &array[3] */
636     errs += pack_and_check_expected(combo, "combo", 3, ARR_SIZE, array, expected);
637
638     MPI_Type_free(&combo);
639     MPI_Type_free(&idx_type);
640     MPI_Type_free(&blkidx_type);
641
642     return errs;
643 #undef COUNT
644 }
645
646 #undef check_err
647
648 int parse_args(int argc, char **argv)
649 {
650     /*
651      * int ret;
652      *
653      * while ((ret = getopt(argc, argv, "v")) >= 0)
654      * {
655      * switch (ret) {
656      * case 'v':
657      * verbose = 1;
658      * break;
659      * }
660      * }
661      */
662     if (argc > 1 && strcmp(argv[1], "-v") == 0)
663         verbose = 1;
664     return 0;
665 }