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",
47 MPI_Abort( MPI_COMM_WORLD, 1 );
50 for (i=0; i<icount; i++) {
51 index_displacement[i] = (i * 3 + (i%3));
54 MPI_Type_create_indexed_block( icount, 1, index_displacement, MPI_DOUBLE,
56 MPI_Type_commit( &itype1 );
58 #if defined(MPICH) && defined(PRINT_DATATYPE_INTERNALS)
59 /* To use MPIDU_Datatype_debug to print the datatype internals,
60 you must configure MPICH with --enable-g=log */
62 printf( "Block index datatype:\n" );
63 MPIDU_Datatype_debug( itype1, 10 );
66 MPI_Type_get_extent( itype1, &lb, &extent );
68 MPI_Pack_size( 1, itype1, MPI_COMM_WORLD, &packsize );
70 inbufsize = extent / sizeof(double);
72 inbuf = (double *)malloc( extent );
73 outbuf = (double *)malloc( packsize );
74 outbuf2 = (double *)malloc( icount * sizeof(double) );
76 fprintf( stderr, "Unable to allocate %ld for inbuf\n", (long)extent );
77 MPI_Abort( MPI_COMM_WORLD, 1 );
80 fprintf( stderr, "Unable to allocate %ld for outbuf\n", (long)packsize );
81 MPI_Abort( MPI_COMM_WORLD, 1 );
84 fprintf( stderr, "Unable to allocate %ld for outbuf2\n", (long)packsize );
85 MPI_Abort( MPI_COMM_WORLD, 1 );
87 for (i=0; i<inbufsize; i++) {
91 /* Warm up the code and data */
92 MPI_Pack( inbuf, 1, itype1, outbuf, packsize, &position, MPI_COMM_WORLD );
95 for (ntry = 0; ntry < 5; ntry++) {
98 MPI_Pack( inbuf, 1, itype1, outbuf, packsize, &position,
100 t1 = MPI_Wtime() - t0;
101 if (t1 < tpack) tpack = t1;
104 { int one = 1; 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,
119 t1 = MPI_Wtime() - t0;
120 if (t1 < tspack) tspack = t1;
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;
133 for (i=0; i<icount; i++) {
134 outbuf2[position++] = ppe[id[i]];
136 t1 = MPI_Wtime() - t0;
137 if (t1 < tmanual) tmanual = t1;
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",
150 printf( "Pack with struct = %e\n", tspack );
153 /* The threshold here permits the MPI datatype to perform at up to
154 only one half the performance of simple user code. Note that the
155 example code above may be made faster through careful use of const,
156 restrict, and unrolling if the compiler doesn't already do that. */
157 if (2 * tmanual < tpack) {
159 printf( "MPI_Pack (block index) time = %e, manual pack time = %e\n", tpack, tmanual );
160 printf( "MPI_Pack time should be less than 2 times the manual time\n" );
161 printf( "For most informative results, be sure to compile this test with optimization\n" );
163 if (2 * tmanual < tspack) {
165 printf( "MPI_Pack (struct of block index)) time = %e, manual pack time = %e\n", tspack, tmanual );
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 );