1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
3 * (C) 2001 by Argonne National Laboratory.
4 * See COPYRIGHT in top-level directory.
9 #include "mpitestconf.h"
16 static int verbose = 1;
18 #define check(cond_) \
22 fprintf(stderr, "condition '%s' does not hold, at line %d\n", #cond_, __LINE__); \
28 #define check_err(err_, what_failed_) \
32 fprintf(stderr, "error: %s, at line %d\n", (what_failed_), __LINE__); \
39 int indexed_contig_test(void);
40 int indexed_zeroblock_first_test(void);
41 int indexed_zeroblock_middle_test(void);
42 int indexed_zeroblock_last_test(void);
43 int indexed_contig_leading_zero_test(void);
44 int indexed_same_lengths(void);
46 /* helper functions */
47 int parse_args(int argc, char **argv);
48 static int pack_and_unpack(char *typebuf,
50 MPI_Datatype datatype,
53 int main(int argc, char **argv)
57 MPI_Init(&argc, &argv); /* MPI-1.2 doesn't allow for MPI_Init(0,0) */
58 parse_args(argc, argv);
60 /* To improve reporting of problems about operations, we
61 change the error handler to errors return */
62 MPI_Comm_set_errhandler( MPI_COMM_WORLD, MPI_ERRORS_RETURN );
64 /* perform some tests */
65 err = indexed_contig_test();
66 if (err && verbose) fprintf(stderr,
67 "%d errors in indexed_contig_test.\n",
71 err = indexed_zeroblock_first_test();
72 if (err && verbose) fprintf(stderr,
73 "%d errors in indexed_zeroblock_first_test.\n",
77 err = indexed_zeroblock_middle_test();
78 if (err && verbose) fprintf(stderr,
79 "%d errors in indexed_zeroblock_middle_test.\n",
83 err = indexed_zeroblock_last_test();
84 if (err && verbose) fprintf(stderr,
85 "%d errors in indexed_zeroblock_last_test.\n",
89 err = indexed_contig_leading_zero_test();
90 if (err && verbose) fprintf(stderr,
91 "%d errors in indexed_contig_leading_zero_test.\n",
95 err = indexed_same_lengths();
96 if (err && verbose) fprintf(stderr,
97 "%d errors in indexed_contig_leading_zero_test.\n",
101 /* print message and exit */
103 fprintf(stderr, "Found %d errors\n", errs);
106 printf(" No Errors\n");
112 int indexed_zeroblock_first_test(void)
117 int len[3] = { 0, 1, 1 };
118 int disp[3] = { 0, 1, 4 };
121 err = MPI_Type_indexed(3, len, disp, MPI_INT, &type);
122 if (err != MPI_SUCCESS) {
125 "error creating indexed type in indexed_zeroblock_first_test()\n");
130 MPI_Type_lb(type, &lb);
131 if (lb != sizeof(int)) {
134 "lb mismatch; is %d, should be %d\n",
135 (int) lb, (int) sizeof(int));
139 MPI_Type_ub(type, &ub);
140 if (ub != 5 * sizeof(int)) {
143 "ub mismatch; is %d, should be %d\n",
144 (int) ub, (int) (5 * sizeof(int)));
149 MPI_Type_free( &type );
154 int indexed_zeroblock_middle_test(void)
159 int len[3] = { 1, 0, 1 };
160 int disp[3] = { 1, 2, 4 };
163 err = MPI_Type_indexed(3, len, disp, MPI_INT, &type);
164 if (err != MPI_SUCCESS) {
167 "error creating indexed type in indexed_zeroblock_middle_test()\n");
172 MPI_Type_lb(type, &lb);
173 if (lb != sizeof(int)) {
176 "lb mismatch; is %d, should be %d\n",
177 (int) lb, (int) sizeof(int));
181 MPI_Type_ub(type, &ub);
182 if (ub != 5 * sizeof(int)) {
185 "ub mismatch; is %d, should be %d\n",
186 (int) ub, (int) (5 * sizeof(int)));
191 MPI_Type_free( &type );
196 int indexed_zeroblock_last_test(void)
201 int len[3] = { 1, 1, 0 };
202 int disp[3] = { 1, 4, 8 };
205 err = MPI_Type_indexed(3, len, disp, MPI_INT, &type);
206 if (err != MPI_SUCCESS) {
209 "error creating indexed type in indexed_zeroblock_last_test()\n");
214 MPI_Type_lb(type, &lb);
215 if (lb != sizeof(int)) {
218 "lb mismatch; is %d, should be %d\n",
219 (int) lb, (int) sizeof(int));
223 MPI_Type_ub(type, &ub);
224 if (ub != 5 * sizeof(int)) {
227 "ub mismatch; is %d, should be %d\n",
228 (int) ub, (int) (5 * sizeof(int)));
233 MPI_Type_free( &type );
238 /* indexed_contig_test()
240 * Tests behavior with an indexed array that can be compacted but should
241 * continue to be stored as an indexed type. Specifically for coverage.
243 * Returns the number of errors encountered.
245 int indexed_contig_test(void)
247 int buf[9] = {-1, 1, 2, 3, -2, 4, 5, -3, 6};
251 int blklen[] = { 1, 2, 1, 1, 1 };
252 int disp[] = { 1, 2, 5, 6, 8 };
253 MPI_Datatype newtype;
257 err = MPI_Type_indexed(count,
262 if (err != MPI_SUCCESS) {
265 "error creating indexed type in indexed_contig_test()\n");
270 MPI_Type_size(MPI_INT, &int_size);
272 err = MPI_Type_size(newtype, &size);
273 if (err != MPI_SUCCESS) {
276 "error obtaining type size in indexed_contig_test()\n");
281 if (size != 6 * int_size) {
284 "error: size != 6 * int_size in indexed_contig_test()\n");
289 MPI_Type_commit(&newtype);
291 err = pack_and_unpack((char *) buf, 1, newtype, 9 * sizeof(int));
295 "error packing/unpacking in indexed_contig_test()\n");
300 for (i=0; i < 9; i++) {
323 goodval = 0; /* pack_and_unpack() zeros before unpack */
326 if (buf[i] != goodval) {
328 if (verbose) fprintf(stderr, "buf[%d] = %d; should be %d\n",
333 MPI_Type_free( &newtype );
338 /* very similar to indexed_zeroblock_first_test, but only has a single contig in
339 * order to catch a particular optimization path in MPICH's
340 * Dataloop_create_indexed routine */
341 int indexed_contig_leading_zero_test(void)
346 MPI_Datatype type = MPI_DATATYPE_NULL;
347 MPI_Datatype struct_type = MPI_DATATYPE_NULL;
348 MPI_Datatype types[2];
349 int len[3] = { 0, 4, 0 };
350 int disp[3] = { INT_MAX, 2, INT_MAX};
355 err = MPI_Type_indexed(3, len, disp, MPI_INT, &type);
356 check_err(err, "creating indexed type in indexed_contig_leading_zero_test()");
357 err = MPI_Type_commit(&type);
358 check_err(err, "committing indexed type in indexed_contig_leading_zero_test()");
360 MPI_Type_lb(type, &lb);
361 check(lb == 2 * sizeof(int));
362 MPI_Type_ub(type, &ub);
363 check(ub == 6 * sizeof(int));
365 /* make sure packing/unpacking works (hits a simple "is_contig" case in
366 * MPICH's pack/unpack routines) */
367 buf = malloc(10*sizeof(int));
369 for (i = 0; i < 10; ++i) {
372 err = pack_and_unpack((char *) buf, 1, type, 10 * sizeof(int));
373 check_err(err, "packing/unpacking in indexed_contig_leading_zero_test()");
374 for (i = 0; i < 10; ++i) {
380 check(buf[i] == expected);
384 /* -------------------------------------------------------------------- */
385 /* A more rigorous test of the indexed type. Use a hard-to-optimize struct
386 * type to force a more complicated datatype processing path
387 * (MPID_Segment_manipulate in MPICH) */
391 adisp[1] = 8*sizeof(int);
395 /* struct layout: xx0123xx4x ('x' indicates a hole), one char is an
397 MPI_Type_create_struct(2, len, adisp, types, &struct_type);
398 check_err(err, "creating struct type in indexed_contig_leading_zero_test()");
399 err = MPI_Type_commit(&struct_type);
400 check_err(err, "committing struct type in indexed_contig_leading_zero_test()");
402 buf = malloc(10*sizeof(int));
404 for (i = 0; i < 10; ++i) {
407 err = pack_and_unpack((char *) buf, 1, struct_type, 10 * sizeof(int));
408 check_err(err, "packing/unpacking in indexed_contig_test()");
410 for (i = 0; i < 10; ++i) {
412 if ((i >= 2 && i < 6) || i == 8)
416 check(buf[i] == expected);
420 MPI_Type_free(&struct_type);
421 MPI_Type_free( &type );
423 /* -------------------------------------------------------------------- */
424 /* now do the same as above, but with hindexed */
428 /* use *_MAX vars to improve our chances of hitting any pointer-casting
429 * bugs in a big way (segfaults, etc.) */
430 /* FIXME: This should also look at long, or use a different approach */
431 #if defined(HAVE_LONG_LONG) && defined(LLONG_MAX)
432 if (sizeof(MPI_Aint) == sizeof(long long)) {
433 adisp[0] = (MPI_Aint)LLONG_MAX;
434 adisp[1] = 2*sizeof(int);
435 adisp[2] = (MPI_Aint)LLONG_MAX;
440 adisp[0] = (MPI_Aint)INT_MAX;
441 adisp[1] = 2*sizeof(int);
442 adisp[2] = (MPI_Aint)INT_MAX;
445 err = MPI_Type_hindexed(3, len, adisp, MPI_INT, &type);
446 check_err(err, "creating hindexed type in indexed_contig_leading_zero_test()");
448 err = MPI_Type_commit(&type);
449 check_err(err, "committing hindexed type in indexed_contig_leading_zero_test()");
451 MPI_Type_lb(type, &lb);
452 check(lb == 2 * sizeof(int));
453 MPI_Type_ub(type, &ub);
454 check(ub == 6 * sizeof(int));
456 buf = malloc(10*sizeof(int));
458 for (i = 0; i < 10; ++i) {
461 err = pack_and_unpack((char *) buf, 1, type, 10 * sizeof(int));
462 check_err(err, "packing/unpacking in indexed_contig_test()");
464 for (i = 0; i < 10; ++i) {
470 check(buf[i] == expected);
475 /* -------------------------------------------------------------------- */
476 /* A more rigorous test of the hindexed type. Use a hard-to-optimize struct
477 * type to force a more complicated datatype processing path
478 * (MPID_Segment_manipulate in MPICH) */
482 adisp[1] = 8*sizeof(int);
484 /* struct layout: xx0123xx4x ('x' indicates a hole), one char is an
486 err = MPI_Type_create_struct(2, len, adisp, types, &struct_type);
487 check_err(err, "committing struct type in indexed_contig_leading_zero_test()");
488 err = MPI_Type_commit(&struct_type);
489 check_err(err, "committing struct type in indexed_contig_leading_zero_test()");
491 buf = malloc(10*sizeof(int));
493 for (i = 0; i < 10; ++i) {
496 /* fails in old MPICH (3.0rc1 and earlier), despite correct ub/lb
498 err = pack_and_unpack((char *) buf, 1, struct_type, 10 * sizeof(int));
499 check_err(err, "packing/unpacking in indexed_contig_test()");
501 for (i = 0; i < 10; ++i) {
503 if ((i >= 2 && i < 6) || i == 8)
507 check(buf[i] == expected);
511 MPI_Type_free(&struct_type);
512 MPI_Type_free(&type);
517 /* Test an indexed (and hindexed) type where the block length is the same for
518 * all blocks, but with differing displacements so that it cannot directly be
519 * converted to a vector type. It is also important to add a dummy element at
520 * the beginning in order to cause int/MPI_Aint misalignment for the
521 * displacement of the first non-zero-width component. */
522 int indexed_same_lengths(void)
527 MPI_Datatype type = MPI_DATATYPE_NULL;
544 err = MPI_Type_indexed(4, len, disp, MPI_INT, &type);
545 check_err(err, "creating indexed type in indexed_same_lengths()");
546 err = MPI_Type_commit(&type);
547 check_err(err, "committing indexed type in indexed_same_lengths()");
549 MPI_Type_lb(type, &lb);
550 check(lb == 1 * sizeof(int));
551 MPI_Type_ub(type, &ub);
552 check(ub == 9 * sizeof(int));
554 buf = malloc(10*sizeof(int));
556 for (i = 0; i < 10; ++i) {
559 err = pack_and_unpack((char *) buf, 1, type, 10 * sizeof(int));
560 check_err(err, "packing/unpacking in indexed_same_lengths()");
561 for (i = 0; i < 10; ++i) {
563 if (i == 1 || i == 3 || i == 8)
567 check(buf[i] == expected);
571 MPI_Type_free(&type);
573 /* -------------------------------------------------------------------- */
574 /* now do the same as above, but with hindexed */
580 adisp[0] = 0 * sizeof(int);
581 adisp[1] = 1 * sizeof(int);
582 adisp[2] = 3 * sizeof(int);
583 adisp[3] = 8 * sizeof(int);
585 err = MPI_Type_hindexed(4, len, adisp, MPI_INT, &type);
586 check_err(err, "creating hindexed type in indexed_same_lengths()");
587 err = MPI_Type_commit(&type);
588 check_err(err, "committing hindexed type in indexed_same_lengths()");
590 MPI_Type_lb(type, &lb);
591 check(lb == 1 * sizeof(int));
592 MPI_Type_ub(type, &ub);
593 check(ub == 9 * sizeof(int));
595 buf = malloc(10*sizeof(int));
597 for (i = 0; i < 10; ++i) {
600 err = pack_and_unpack((char *) buf, 1, type, 10 * sizeof(int));
601 check_err(err, "packing/unpacking in indexed_same_lengths()");
602 for (i = 0; i < 10; ++i) {
604 if (i == 1 || i == 3 || i == 8)
608 check(buf[i] == expected);
612 MPI_Type_free(&type);
619 * Perform packing and unpacking of a buffer for the purposes of checking
620 * to see if we are processing a type correctly. Zeros the buffer between
621 * these two operations, so the data described by the type should be in
622 * place upon return but all other regions of the buffer should be zero.
625 * typebuf - pointer to buffer described by datatype and count that
626 * will be packed and then unpacked into
627 * count, datatype - description of typebuf
628 * typebufsz - size of typebuf; used specifically to zero the buffer
629 * between the pack and unpack steps
632 static int pack_and_unpack(char *typebuf,
634 MPI_Datatype datatype,
638 int err, errs = 0, pack_size, type_size, position;
640 err = MPI_Type_size(datatype, &type_size);
641 if (err != MPI_SUCCESS) {
645 "error in MPI_Type_size call; aborting after %d errors\n",
653 err = MPI_Pack_size(count, datatype, MPI_COMM_SELF, &pack_size);
654 if (err != MPI_SUCCESS) {
658 "error in MPI_Pack_size call; aborting after %d errors\n",
663 packbuf = (char *) malloc(pack_size);
664 if (packbuf == NULL) {
668 "error in malloc call; aborting after %d errors\n",
675 err = MPI_Pack(typebuf,
683 if (position != type_size) {
685 if (verbose) fprintf(stderr, "position = %d; should be %d (pack)\n",
686 position, type_size);
689 memset(typebuf, 0, typebufsz);
691 err = MPI_Unpack(packbuf,
698 if (err != MPI_SUCCESS) {
702 "error in MPI_Unpack call; aborting after %d errors\n",
709 if (position != type_size) {
711 if (verbose) fprintf(stderr, "position = %d; should be %d (unpack)\n",
712 position, type_size);
718 int parse_args(int argc, char **argv)
723 while ((ret = getopt(argc, argv, "v")) >= 0)
732 if (argc > 1 && strcmp(argv[1], "-v") == 0)