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 vector of vector datatypes.
9 * As the "leaf" element is a large block (when properly optimized), the
10 * performance of an MPI datatype should be nearly as good (if not better)
11 * than manual packing (the threshold used in this test is *very* forgiving).
12 * This test may be run with one process.
14 * If PACK_IS_NATIVE is defined, MPI_Pack stores exactly the same bytes as the
15 * user would pack manually; in that case, there is a consistency check.
23 #include "mpitestconf.h"
26 /* MPICH (as of 6/2012) packs the native bytes */
27 #define PACK_IS_NATIVE
31 static int verbose = 0;
33 int main( int argc, char **argv )
35 int vcount = 16, vblock = vcount*vcount/2, vstride=2*vcount*vblock;
36 int v2stride, typesize, packsize, i, position, errs = 0;
37 char *inbuf, *outbuf, *outbuf2;
38 MPI_Datatype ft1type, ft2type, ft3type;
39 MPI_Datatype ftopttype;
42 double tpack, tmanual, tpackopt;
45 MPI_Init( &argc, &argv );
47 MPI_Type_contiguous( 6, MPI_FLOAT, &ft1type );
48 MPI_Type_size( ft1type, &typesize );
49 v2stride = vcount * vcount * vcount * vcount * typesize;
50 MPI_Type_vector( vcount, vblock, vstride, ft1type, &ft2type );
51 MPI_Type_create_hvector( 2, 1, v2stride, ft2type, &ft3type );
52 MPI_Type_commit( &ft3type );
53 MPI_Type_free( &ft1type );
54 MPI_Type_free( &ft2type );
55 #if defined(MPICH) && defined(PRINT_DATATYPE_INTERNALS)
56 /* To use MPIDU_Datatype_debug to print the datatype internals,
57 you must configure MPICH with --enable-g=log */
59 printf( "Original datatype:\n" );
60 MPIDU_Datatype_debug( ft3type, 10 );
63 /* The same type, but without using the contiguous type */
64 MPI_Type_vector( vcount, 6*vblock, 6*vstride, MPI_FLOAT, &ft2type );
65 MPI_Type_create_hvector( 2, 1, v2stride, ft2type, &ftopttype );
66 MPI_Type_commit( &ftopttype );
67 MPI_Type_free( &ft2type );
68 #if defined(MPICH) && defined(PRINT_DATATYPE_INTERNALS)
70 printf( "\n\nMerged datatype:\n" );
71 MPIDU_Datatype_debug( ftopttype, 10 );
75 MPI_Type_get_extent( ft3type, &lb, &extent );
76 MPI_Type_size( ft3type, &typesize );
78 MPI_Pack_size( 1, ft3type, MPI_COMM_WORLD, &packsize );
80 inbuf = (char *)malloc( extent );
81 outbuf = (char *)malloc( packsize );
82 outbuf2 = (char *)malloc( packsize );
84 fprintf( stderr, "Unable to allocate %ld for inbuf\n", (long)extent );
85 MPI_Abort( MPI_COMM_WORLD, 1 );
88 fprintf( stderr, "Unable to allocate %ld for outbuf\n", (long)packsize );
89 MPI_Abort( MPI_COMM_WORLD, 1 );
92 fprintf( stderr, "Unable to allocate %ld for outbuf2\n", (long)packsize );
93 MPI_Abort( MPI_COMM_WORLD, 1 );
95 for (i=0; i<extent; i++) {
99 /* Warm up the code and data */
100 MPI_Pack( inbuf, 1, ft3type, outbuf, packsize, &position, MPI_COMM_WORLD );
102 /* Pack using the vector of vector of contiguous */
104 for (ntry = 0; ntry < 5; ntry++) {
107 MPI_Pack( inbuf, 1, ft3type, outbuf, packsize, &position,
109 t1 = MPI_Wtime() - t0;
110 if (t1 < tpack) tpack = t1;
112 MPI_Type_free( &ft3type );
114 /* Pack using vector of vector with big blocks (same type map) */
116 for (ntry = 0; ntry < 5; ntry++) {
119 MPI_Pack( inbuf, 1, ftopttype, outbuf, packsize, &position,
121 t1 = MPI_Wtime() - t0;
122 if (t1 < tpackopt) tpackopt = t1;
124 MPI_Type_free( &ftopttype );
126 /* User (manual) packing code.
127 Note that we exploit the fact that the vector type contains vblock
128 instances of a contiguous type of size 24, or equivalently a
129 single block of 24*vblock bytes.
132 for (ntry = 0; ntry < 5; ntry++) {
133 const char *ppe = (const char *)inbuf;
137 for (k=0; k<2; k++) { /* hvector count; blocksize is 1 */
138 const char *ptr = ppe;
139 for (j=0; j<vcount; j++) { /* vector count */
140 memcpy( outbuf2 + position, ptr, 24*vblock );
142 position += 24*vblock;
146 t1 = MPI_Wtime() - t0;
147 if (t1 < tmanual) tmanual = t1;
149 /* Check on correctness */
150 #ifdef PACK_IS_NATIVE
151 if (memcmp( outbuf, outbuf2, position ) != 0) {
152 printf( "Panic - pack buffers differ\n" );
158 printf( "Bytes packed = %d\n", position );
159 printf( "MPI_Pack time = %e, opt version = %e, manual pack time = %e\n",
160 tpack, tpackopt, tmanual );
163 /* A factor of 4 is extremely generous, especially since the test suite
164 no longer builds any of the tests with optimization */
165 if (4 * tmanual < tpack) {
167 printf( "MPI_Pack time = %e, manual pack time = %e\n", tpack, tmanual );
168 printf( "MPI_Pack time should be less than 4 times the manual time\n" );
169 printf( "For most informative results, be sure to compile this test with optimization\n" );
171 if (4 * tmanual < tpackopt) {
173 printf( "MPI_Pack with opt = %e, manual pack time = %e\n", tpackopt,
175 printf( "MPI_Pack time should be less than 4 times the manual time\n" );
176 printf( "For most informative results, be sure to compile this test with optimization\n" );
179 printf( " Found %d errors\n", errs );
182 printf( " No Errors\n" );