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.
7 #include "mpitestconf.h"
14 static int verbose = 0;
17 int builtin_float_test(void);
18 int vector_of_vectors_test(void);
19 int optimizable_vector_of_basics_test(void);
20 int indexed_of_basics_test(void);
21 int indexed_of_vectors_test(void);
22 int struct_of_basics_test(void);
24 /* helper functions */
25 char *combiner_to_string(int combiner);
26 int parse_args(int argc, char **argv);
28 int main(int argc, char **argv)
32 MPI_Init(&argc, &argv); /* MPI-1.2 doesn't allow for MPI_Init(0,0) */
33 parse_args(argc, argv);
35 /* To improve reporting of problems about operations, we
36 * change the error handler to errors return */
37 MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
39 /* perform some tests */
40 err = builtin_float_test();
43 fprintf(stderr, "Found %d errors in builtin float test.\n", err);
46 err = vector_of_vectors_test();
49 fprintf(stderr, "Found %d errors in vector of vectors test.\n", err);
52 err = optimizable_vector_of_basics_test();
55 fprintf(stderr, "Found %d errors in vector of basics test.\n", err);
58 err = indexed_of_basics_test();
61 fprintf(stderr, "Found %d errors in indexed of basics test.\n", err);
64 err = indexed_of_vectors_test();
67 fprintf(stderr, "Found %d errors in indexed of vectors test.\n", err);
70 #ifdef HAVE_MPI_TYPE_CREATE_STRUCT
71 err = struct_of_basics_test();
75 /* print message and exit */
77 fprintf(stderr, "Found %d errors\n", errs);
80 printf(" No Errors\n");
86 /* builtin_float_test()
88 * Tests functionality of get_envelope() and get_contents() on a MPI_FLOAT.
90 * Returns the number of errors encountered.
92 int builtin_float_test(void)
94 int nints, nadds, ntypes, combiner;
98 err = MPI_Type_get_envelope(MPI_FLOAT, &nints, &nadds, &ntypes, &combiner);
100 if (combiner != MPI_COMBINER_NAMED || err != MPI_SUCCESS)
102 if (verbose && combiner != MPI_COMBINER_NAMED)
103 fprintf(stderr, "combiner = %s; should be named\n", combiner_to_string(combiner));
105 /* Note: it is erroneous to call MPI_Type_get_contents() on a basic. */
109 /* vector_of_vectors_test()
111 * Builds a vector of a vector of ints. Assuming an int array of size 9
112 * integers, and treating the array as a 3x3 2D array, this will grab the
115 * Returns the number of errors encountered.
117 int vector_of_vectors_test(void)
119 MPI_Datatype inner_vector, inner_vector_copy;
120 MPI_Datatype outer_vector;
122 int nints, nadds, ntypes, combiner, *ints;
123 MPI_Aint *adds = NULL;
129 err = MPI_Type_vector(2, 1, 2, MPI_INT, &inner_vector);
130 if (err != MPI_SUCCESS) {
132 fprintf(stderr, "error in MPI call; aborting after %d errors\n", errs + 1);
136 err = MPI_Type_vector(2, 1, 2, inner_vector, &outer_vector);
137 if (err != MPI_SUCCESS) {
139 fprintf(stderr, "error in MPI call; aborting after %d errors\n", errs + 1);
143 /* decode outer vector (get envelope, then contents) */
144 err = MPI_Type_get_envelope(outer_vector, &nints, &nadds, &ntypes, &combiner);
145 if (err != MPI_SUCCESS) {
147 fprintf(stderr, "error in MPI call; aborting after %d errors\n", errs + 1);
157 if (combiner != MPI_COMBINER_VECTOR)
162 fprintf(stderr, "outer vector nints = %d; should be 3\n", nints);
164 fprintf(stderr, "outer vector nadds = %d; should be 0\n", nadds);
166 fprintf(stderr, "outer vector ntypes = %d; should be 1\n", ntypes);
167 if (combiner != MPI_COMBINER_VECTOR)
168 fprintf(stderr, "outer vector combiner = %s; should be vector\n",
169 combiner_to_string(combiner));
173 fprintf(stderr, "aborting after %d errors\n", errs);
177 ints = malloc(nints * sizeof(*ints));
179 adds = malloc(nadds * sizeof(*adds));
180 types = malloc(ntypes * sizeof(*types));
182 /* get contents of outer vector */
183 err = MPI_Type_get_contents(outer_vector, nints, nadds, ntypes, ints, adds, types);
194 fprintf(stderr, "outer vector count = %d; should be 2\n", ints[0]);
196 fprintf(stderr, "outer vector blocklength = %d; should be 1\n", ints[1]);
198 fprintf(stderr, "outer vector stride = %d; should be 2\n", ints[2]);
202 fprintf(stderr, "aborting after %d errors\n", errs);
206 inner_vector_copy = types[0];
212 /* decode inner vector */
213 err = MPI_Type_get_envelope(inner_vector_copy, &nints, &nadds, &ntypes, &combiner);
214 if (err != MPI_SUCCESS) {
216 fprintf(stderr, "error in MPI call; aborting after %d errors\n", errs + 1);
226 if (combiner != MPI_COMBINER_VECTOR)
231 fprintf(stderr, "inner vector nints = %d; should be 3\n", nints);
233 fprintf(stderr, "inner vector nadds = %d; should be 0\n", nadds);
235 fprintf(stderr, "inner vector ntypes = %d; should be 1\n", ntypes);
236 if (combiner != MPI_COMBINER_VECTOR)
237 fprintf(stderr, "inner vector combiner = %s; should be vector\n",
238 combiner_to_string(combiner));
242 fprintf(stderr, "aborting after %d errors\n", errs);
246 ints = malloc(nints * sizeof(*ints));
248 adds = malloc(nadds * sizeof(*adds));
249 types = malloc(ntypes * sizeof(*types));
251 err = MPI_Type_get_contents(inner_vector_copy, nints, nadds, ntypes, ints, adds, types);
262 fprintf(stderr, "inner vector count = %d; should be 2\n", ints[0]);
264 fprintf(stderr, "inner vector blocklength = %d; should be 1\n", ints[1]);
266 fprintf(stderr, "inner vector stride = %d; should be 2\n", ints[2]);
270 fprintf(stderr, "aborting after %d errors\n", errs);
279 MPI_Type_free(&inner_vector_copy);
280 MPI_Type_free(&inner_vector);
281 MPI_Type_free(&outer_vector);
286 /* optimizable_vector_of_basics_test()
288 * Builds a vector of ints. Count is 10, blocksize is 2, stride is 2, so this
289 * is equivalent to a contig of 20. But remember...we should get back our
290 * suboptimal values under MPI-2.
292 * Returns the number of errors encountered.
294 int optimizable_vector_of_basics_test(void)
296 MPI_Datatype parent_type;
298 int nints, nadds, ntypes, combiner, *ints;
299 MPI_Aint *adds = NULL;
305 err = MPI_Type_vector(10, 2, 2, MPI_INT, &parent_type);
308 err = MPI_Type_get_envelope(parent_type, &nints, &nadds, &ntypes, &combiner);
310 if (nints != 3 || err != MPI_SUCCESS)
316 if (combiner != MPI_COMBINER_VECTOR)
321 fprintf(stderr, "nints = %d; should be 3\n", nints);
323 fprintf(stderr, "nadds = %d; should be 0\n", nadds);
325 fprintf(stderr, "ntypes = %d; should be 1\n", ntypes);
326 if (combiner != MPI_COMBINER_VECTOR)
327 fprintf(stderr, "combiner = %s; should be vector\n", combiner_to_string(combiner));
330 ints = malloc(nints * sizeof(*ints));
332 adds = malloc(nadds * sizeof(*adds));
333 types = malloc(ntypes * sizeof(*types));
335 err = MPI_Type_get_contents(parent_type, nints, nadds, ntypes, ints, adds, types);
343 if (types[0] != MPI_INT)
348 fprintf(stderr, "count = %d; should be 10\n", ints[0]);
350 fprintf(stderr, "blocklength = %d; should be 2\n", ints[1]);
352 fprintf(stderr, "stride = %d; should be 2\n", ints[2]);
353 if (types[0] != MPI_INT)
354 fprintf(stderr, "type is not MPI_INT\n");
362 MPI_Type_free(&parent_type);
368 /* indexed_of_basics_test(void)
370 * Simple indexed type.
372 * Returns number of errors encountered.
374 int indexed_of_basics_test(void)
376 MPI_Datatype parent_type;
377 int s_count = 3, s_blocklengths[3] = { 3, 2, 1 };
378 int s_displacements[3] = { 10, 20, 30 };
380 int nints, nadds, ntypes, combiner, *ints;
381 MPI_Aint *adds = NULL;
387 err = MPI_Type_indexed(s_count, s_blocklengths, s_displacements, MPI_INT, &parent_type);
390 err = MPI_Type_get_envelope(parent_type, &nints, &nadds, &ntypes, &combiner);
392 if (nints != 7 || err != MPI_SUCCESS)
398 if (combiner != MPI_COMBINER_INDEXED)
403 fprintf(stderr, "nints = %d; should be 7\n", nints);
405 fprintf(stderr, "nadds = %d; should be 0\n", nadds);
407 fprintf(stderr, "ntypes = %d; should be 1\n", ntypes);
408 if (combiner != MPI_COMBINER_INDEXED)
409 fprintf(stderr, "combiner = %s; should be indexed\n", combiner_to_string(combiner));
412 ints = malloc(nints * sizeof(*ints));
414 adds = malloc(nadds * sizeof(*adds));
415 types = malloc(ntypes * sizeof(*types));
417 err = MPI_Type_get_contents(parent_type, nints, nadds, ntypes, ints, adds, types);
419 if (ints[0] != s_count)
421 if (ints[1] != s_blocklengths[0])
423 if (ints[2] != s_blocklengths[1])
425 if (ints[3] != s_blocklengths[2])
427 if (ints[4] != s_displacements[0])
429 if (ints[5] != s_displacements[1])
431 if (ints[6] != s_displacements[2])
433 if (types[0] != MPI_INT)
437 if (ints[0] != s_count)
438 fprintf(stderr, "count = %d; should be %d\n", ints[0], s_count);
439 if (ints[1] != s_blocklengths[0])
440 fprintf(stderr, "blocklength[0] = %d; should be %d\n", ints[1], s_blocklengths[0]);
441 if (ints[2] != s_blocklengths[1])
442 fprintf(stderr, "blocklength[1] = %d; should be %d\n", ints[2], s_blocklengths[1]);
443 if (ints[3] != s_blocklengths[2])
444 fprintf(stderr, "blocklength[2] = %d; should be %d\n", ints[3], s_blocklengths[2]);
445 if (ints[4] != s_displacements[0])
446 fprintf(stderr, "displacement[0] = %d; should be %d\n", ints[4], s_displacements[0]);
447 if (ints[5] != s_displacements[1])
448 fprintf(stderr, "displacement[1] = %d; should be %d\n", ints[5], s_displacements[1]);
449 if (ints[6] != s_displacements[2])
450 fprintf(stderr, "displacement[2] = %d; should be %d\n", ints[6], s_displacements[2]);
451 if (types[0] != MPI_INT)
452 fprintf(stderr, "type[0] does not match\n");
460 MPI_Type_free(&parent_type);
464 /* indexed_of_vectors_test()
466 * Builds an indexed type of vectors of ints.
468 * Returns the number of errors encountered.
470 int indexed_of_vectors_test(void)
472 MPI_Datatype inner_vector, inner_vector_copy;
473 MPI_Datatype outer_indexed;
475 int i_count = 3, i_blocklengths[3] = { 3, 2, 1 };
476 int i_displacements[3] = { 10, 20, 30 };
478 int nints, nadds, ntypes, combiner, *ints;
479 MPI_Aint *adds = NULL;
485 err = MPI_Type_vector(2, 1, 2, MPI_INT, &inner_vector);
486 if (err != MPI_SUCCESS) {
488 fprintf(stderr, "error in MPI call; aborting after %d errors\n", errs + 1);
492 err = MPI_Type_indexed(i_count, i_blocklengths, i_displacements, inner_vector, &outer_indexed);
493 if (err != MPI_SUCCESS) {
495 fprintf(stderr, "error in MPI call; aborting after %d errors\n", errs + 1);
499 /* decode outer vector (get envelope, then contents) */
500 err = MPI_Type_get_envelope(outer_indexed, &nints, &nadds, &ntypes, &combiner);
501 if (err != MPI_SUCCESS) {
503 fprintf(stderr, "error in MPI call; aborting after %d errors\n", errs + 1);
513 if (combiner != MPI_COMBINER_INDEXED)
518 fprintf(stderr, "nints = %d; should be 7\n", nints);
520 fprintf(stderr, "nadds = %d; should be 0\n", nadds);
522 fprintf(stderr, "ntypes = %d; should be 1\n", ntypes);
523 if (combiner != MPI_COMBINER_INDEXED)
524 fprintf(stderr, "combiner = %s; should be indexed\n", combiner_to_string(combiner));
529 fprintf(stderr, "aborting after %d errors\n", errs);
533 ints = malloc(nints * sizeof(*ints));
535 adds = malloc(nadds * sizeof(*adds));
536 types = malloc(ntypes * sizeof(*types));
538 /* get contents of outer vector */
539 err = MPI_Type_get_contents(outer_indexed, nints, nadds, ntypes, ints, adds, types);
541 if (ints[0] != i_count)
543 if (ints[1] != i_blocklengths[0])
545 if (ints[2] != i_blocklengths[1])
547 if (ints[3] != i_blocklengths[2])
549 if (ints[4] != i_displacements[0])
551 if (ints[5] != i_displacements[1])
553 if (ints[6] != i_displacements[2])
557 if (ints[0] != i_count)
558 fprintf(stderr, "count = %d; should be %d\n", ints[0], i_count);
559 if (ints[1] != i_blocklengths[0])
560 fprintf(stderr, "blocklength[0] = %d; should be %d\n", ints[1], i_blocklengths[0]);
561 if (ints[2] != i_blocklengths[1])
562 fprintf(stderr, "blocklength[1] = %d; should be %d\n", ints[2], i_blocklengths[1]);
563 if (ints[3] != i_blocklengths[2])
564 fprintf(stderr, "blocklength[2] = %d; should be %d\n", ints[3], i_blocklengths[2]);
565 if (ints[4] != i_displacements[0])
566 fprintf(stderr, "displacement[0] = %d; should be %d\n", ints[4], i_displacements[0]);
567 if (ints[5] != i_displacements[1])
568 fprintf(stderr, "displacement[1] = %d; should be %d\n", ints[5], i_displacements[1]);
569 if (ints[6] != i_displacements[2])
570 fprintf(stderr, "displacement[2] = %d; should be %d\n", ints[6], i_displacements[2]);
575 fprintf(stderr, "aborting after %d errors\n", errs);
579 inner_vector_copy = types[0];
585 /* decode inner vector */
586 err = MPI_Type_get_envelope(inner_vector_copy, &nints, &nadds, &ntypes, &combiner);
587 if (err != MPI_SUCCESS) {
589 fprintf(stderr, "error in MPI call; aborting after %d errors\n", errs + 1);
599 if (combiner != MPI_COMBINER_VECTOR)
604 fprintf(stderr, "inner vector nints = %d; should be 3\n", nints);
606 fprintf(stderr, "inner vector nadds = %d; should be 0\n", nadds);
608 fprintf(stderr, "inner vector ntypes = %d; should be 1\n", ntypes);
609 if (combiner != MPI_COMBINER_VECTOR)
610 fprintf(stderr, "inner vector combiner = %s; should be vector\n",
611 combiner_to_string(combiner));
615 fprintf(stderr, "aborting after %d errors\n", errs);
619 ints = malloc(nints * sizeof(*ints));
621 adds = malloc(nadds * sizeof(*adds));
622 types = malloc(ntypes * sizeof(*types));
624 err = MPI_Type_get_contents(inner_vector_copy, nints, nadds, ntypes, ints, adds, types);
635 fprintf(stderr, "inner vector count = %d; should be 2\n", ints[0]);
637 fprintf(stderr, "inner vector blocklength = %d; should be 1\n", ints[1]);
639 fprintf(stderr, "inner vector stride = %d; should be 2\n", ints[2]);
643 fprintf(stderr, "aborting after %d errors\n", errs);
652 MPI_Type_free(&inner_vector_copy);
653 MPI_Type_free(&inner_vector);
654 MPI_Type_free(&outer_indexed);
660 #ifdef HAVE_MPI_TYPE_CREATE_STRUCT
661 /* struct_of_basics_test(void)
663 * There's nothing simple about structs :). Although this is an easy one.
665 * Returns number of errors encountered.
669 int struct_of_basics_test(void)
671 MPI_Datatype parent_type;
672 int s_count = 3, s_blocklengths[3] = { 3, 2, 1 };
673 MPI_Aint s_displacements[3] = { 10, 20, 30 };
674 MPI_Datatype s_types[3] = { MPI_CHAR, MPI_INT, MPI_FLOAT };
676 int nints, nadds, ntypes, combiner, *ints;
677 MPI_Aint *adds = NULL;
683 err = MPI_Type_create_struct(s_count, s_blocklengths, s_displacements, s_types, &parent_type);
686 err = MPI_Type_get_envelope(parent_type, &nints, &nadds, &ntypes, &combiner);
694 if (combiner != MPI_COMBINER_STRUCT)
699 fprintf(stderr, "nints = %d; should be 3\n", nints);
701 fprintf(stderr, "nadds = %d; should be 0\n", nadds);
703 fprintf(stderr, "ntypes = %d; should be 3\n", ntypes);
704 if (combiner != MPI_COMBINER_STRUCT)
705 fprintf(stderr, "combiner = %s; should be struct\n", combiner_to_string(combiner));
708 ints = malloc(nints * sizeof(*ints));
709 adds = malloc(nadds * sizeof(*adds));
710 types = malloc(ntypes * sizeof(*types));
712 err = MPI_Type_get_contents(parent_type, nints, nadds, ntypes, ints, adds, types);
714 if (ints[0] != s_count)
716 if (ints[1] != s_blocklengths[0])
718 if (ints[2] != s_blocklengths[1])
720 if (ints[3] != s_blocklengths[2])
722 if (adds[0] != s_displacements[0])
724 if (adds[1] != s_displacements[1])
726 if (adds[2] != s_displacements[2])
728 if (types[0] != s_types[0])
730 if (types[1] != s_types[1])
732 if (types[2] != s_types[2])
736 if (ints[0] != s_count)
737 fprintf(stderr, "count = %d; should be %d\n", ints[0], s_count);
738 if (ints[1] != s_blocklengths[0])
739 fprintf(stderr, "blocklength[0] = %d; should be %d\n", ints[1], s_blocklengths[0]);
740 if (ints[2] != s_blocklengths[1])
741 fprintf(stderr, "blocklength[1] = %d; should be %d\n", ints[2], s_blocklengths[1]);
742 if (ints[3] != s_blocklengths[2])
743 fprintf(stderr, "blocklength[2] = %d; should be %d\n", ints[3], s_blocklengths[2]);
744 if (adds[0] != s_displacements[0])
745 fprintf(stderr, "displacement[0] = %d; should be %d\n", adds[0], s_displacements[0]);
746 if (adds[1] != s_displacements[1])
747 fprintf(stderr, "displacement[1] = %d; should be %d\n", adds[1], s_displacements[1]);
748 if (adds[2] != s_displacements[2])
749 fprintf(stderr, "displacement[2] = %d; should be %d\n", adds[2], s_displacements[2]);
750 if (types[0] != s_types[0])
751 fprintf(stderr, "type[0] does not match\n");
752 if (types[1] != s_types[1])
753 fprintf(stderr, "type[1] does not match\n");
754 if (types[2] != s_types[2])
755 fprintf(stderr, "type[2] does not match\n");
762 MPI_Type_free(&parent_type);
768 /* combiner_to_string(combiner)
770 * Converts a numeric combiner into a pointer to a string used for printing.
772 char *combiner_to_string(int combiner)
774 static char c_named[] = "named";
775 static char c_contig[] = "contig";
776 static char c_vector[] = "vector";
777 static char c_hvector[] = "hvector";
778 static char c_indexed[] = "indexed";
779 static char c_hindexed[] = "hindexed";
780 static char c_struct[] = "struct";
781 #ifdef HAVE_MPI2_COMBINERS
782 static char c_dup[] = "dup";
783 static char c_hvector_integer[] = "hvector_integer";
784 static char c_hindexed_integer[] = "hindexed_integer";
785 static char c_indexed_block[] = "indexed_block";
786 static char c_struct_integer[] = "struct_integer";
787 static char c_subarray[] = "subarray";
788 static char c_darray[] = "darray";
789 static char c_f90_real[] = "f90_real";
790 static char c_f90_complex[] = "f90_complex";
791 static char c_f90_integer[] = "f90_integer";
792 static char c_resized[] = "resized";
795 if (combiner == MPI_COMBINER_NAMED)
797 if (combiner == MPI_COMBINER_CONTIGUOUS)
799 if (combiner == MPI_COMBINER_VECTOR)
801 if (combiner == MPI_COMBINER_HVECTOR)
803 if (combiner == MPI_COMBINER_INDEXED)
805 if (combiner == MPI_COMBINER_HINDEXED)
807 if (combiner == MPI_COMBINER_STRUCT)
809 #ifdef HAVE_MPI2_COMBINERS
810 if (combiner == MPI_COMBINER_DUP)
812 if (combiner == MPI_COMBINER_HVECTOR_INTEGER)
813 return c_hvector_integer;
814 if (combiner == MPI_COMBINER_HINDEXED_INTEGER)
815 return c_hindexed_integer;
816 if (combiner == MPI_COMBINER_INDEXED_BLOCK)
817 return c_indexed_block;
818 if (combiner == MPI_COMBINER_STRUCT_INTEGER)
819 return c_struct_integer;
820 if (combiner == MPI_COMBINER_SUBARRAY)
822 if (combiner == MPI_COMBINER_DARRAY)
824 if (combiner == MPI_COMBINER_F90_REAL)
826 if (combiner == MPI_COMBINER_F90_COMPLEX)
827 return c_f90_complex;
828 if (combiner == MPI_COMBINER_F90_INTEGER)
829 return c_f90_integer;
830 if (combiner == MPI_COMBINER_RESIZED)
837 int parse_args(int argc, char **argv)
842 while ((ret = getopt(argc, argv, "v")) >= 0) {