1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
3 * (C) 2012 by Argonne National Laboratory.
4 * See COPYRIGHT in top-level directory.
8 * Tests that basic optimizations are performed on indexed datatypes.
10 * If PACK_IS_NATIVE is defined, MPI_Pack stores exactly the same bytes as the
11 * user would pack manually; in that case, there is a consistency check.
15 /* MPICH (as of 6/2012) packs the native bytes */
16 #define PACK_IS_NATIVE
24 static int verbose = 0;
26 int main(int argc, char **argv)
28 double *inbuf, *outbuf, *outbuf2;
30 int *index_displacement;
32 int i, packsize, position, inbufsize;
33 MPI_Datatype itype1, stype1;
35 double tpack, tspack, tmanual;
38 MPI_Init(&argc, &argv);
42 /* Create a simple block indexed datatype */
43 index_displacement = (int *) malloc(icount * sizeof(int));
44 if (!index_displacement) {
45 fprintf(stderr, "Unable to allocated index array of size %d\n", icount);
46 MPI_Abort(MPI_COMM_WORLD, 1);
49 for (i = 0; i < icount; i++) {
50 index_displacement[i] = (i * 3 + (i % 3));
53 MPI_Type_create_indexed_block(icount, 1, index_displacement, MPI_DOUBLE, &itype1);
54 MPI_Type_commit(&itype1);
56 #if defined(MPICH) && defined(PRINT_DATATYPE_INTERNALS)
57 /* To use MPIDU_Datatype_debug to print the datatype internals,
58 * you must configure MPICH with --enable-g=log */
60 printf("Block index datatype:\n");
61 MPIDU_Datatype_debug(itype1, 10);
64 MPI_Type_get_extent(itype1, &lb, &extent);
66 MPI_Pack_size(1, itype1, MPI_COMM_WORLD, &packsize);
68 inbufsize = extent / sizeof(double);
70 inbuf = (double *) malloc(extent);
71 outbuf = (double *) malloc(packsize);
72 outbuf2 = (double *) malloc(icount * sizeof(double));
74 fprintf(stderr, "Unable to allocate %ld for inbuf\n", (long) extent);
75 MPI_Abort(MPI_COMM_WORLD, 1);
78 fprintf(stderr, "Unable to allocate %ld for outbuf\n", (long) packsize);
79 MPI_Abort(MPI_COMM_WORLD, 1);
82 fprintf(stderr, "Unable to allocate %ld for outbuf2\n", (long) packsize);
83 MPI_Abort(MPI_COMM_WORLD, 1);
85 for (i = 0; i < inbufsize; i++) {
86 inbuf[i] = (double) i;
89 /* Warm up the code and data */
90 MPI_Pack(inbuf, 1, itype1, outbuf, packsize, &position, MPI_COMM_WORLD);
93 for (ntry = 0; ntry < 5; ntry++) {
96 MPI_Pack(inbuf, 1, itype1, outbuf, packsize, &position, MPI_COMM_WORLD);
97 t1 = MPI_Wtime() - t0;
104 MPI_Aint displ = (MPI_Aint) inbuf;
105 MPI_Type_create_struct(1, &one, &displ, &itype1, &stype1);
106 MPI_Type_commit(&stype1);
110 /* Warm up the code and data */
111 MPI_Pack(MPI_BOTTOM, 1, stype1, outbuf, packsize, &position, MPI_COMM_WORLD);
114 for (ntry = 0; ntry < 5; ntry++) {
117 MPI_Pack(MPI_BOTTOM, 1, stype1, outbuf, packsize, &position, MPI_COMM_WORLD);
118 t1 = MPI_Wtime() - t0;
124 * Simple manual pack (without explicitly unrolling the index block)
127 for (ntry = 0; ntry < 5; ntry++) {
128 const double *ppe = (const double *) inbuf;
129 const int *id = (const int *) index_displacement;
132 for (i = 0; i < icount; i++) {
133 outbuf2[position++] = ppe[id[i]];
135 t1 = MPI_Wtime() - t0;
138 /* Check on correctness */
139 #ifdef PACK_IS_NATIVE
140 if (memcmp(outbuf, outbuf2, position) != 0) {
141 printf("Panic - pack buffers differ\n");
147 printf("Bytes packed = %d\n", position);
148 printf("MPI_Pack time = %e, manual pack time = %e\n", tpack, tmanual);
149 printf("Pack with struct = %e\n", tspack);
152 /* The threshold here permits the MPI datatype to perform at up to
153 * only one half the performance of simple user code. Note that the
154 * example code above may be made faster through careful use of const,
155 * restrict, and unrolling if the compiler doesn't already do that. */
156 if (2 * tmanual < tpack) {
158 printf("MPI_Pack (block index) time = %e, manual pack time = %e\n", tpack, tmanual);
159 printf("MPI_Pack time should be less than 2 times the manual time\n");
160 printf("For most informative results, be sure to compile this test with optimization\n");
162 if (2 * tmanual < tspack) {
164 printf("MPI_Pack (struct of block index)) time = %e, manual pack time = %e\n", tspack,
166 printf("MPI_Pack time should be less than 2 times the manual time\n");
167 printf("For most informative results, be sure to compile this test with optimization\n");
170 printf(" Found %d errors\n", errs);
173 printf(" No Errors\n");
176 MPI_Type_free(&itype1);
177 MPI_Type_free(&stype1);
182 free(index_displacement);