Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
494f847f203ffe17653bf0e859f6e7f7b435394c
[simgrid.git] / teshsuite / smpi / mpich3-test / perf / nestvec.c
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  *  (C) 2012 by Argonne National Laboratory.
4  *      See COPYRIGHT in top-level directory.
5  */
6
7 /*
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.
13  *
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.
16  */
17
18 #include "mpi.h"
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include "mpitestconf.h"
24
25 #ifdef MPICH
26 /* MPICH (as of 6/2012) packs the native bytes */
27 #define PACK_IS_NATIVE
28 #endif
29
30
31 static int verbose = 0;
32
33 int main( int argc, char **argv )
34 {
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;
40     MPI_Aint     lb, extent;
41     double       t0, t1;
42     double       tpack, tmanual, tpackopt;
43     int          ntry;
44
45     MPI_Init( &argc, &argv );
46     
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 */
58     if (verbose) {
59         printf( "Original datatype:\n" );
60         MPIDU_Datatype_debug( ft3type, 10 );
61     }
62 #endif
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)
69     if (verbose) {
70         printf( "\n\nMerged datatype:\n" );
71         MPIDU_Datatype_debug( ftopttype, 10 );
72     }
73 #endif
74
75     MPI_Type_get_extent( ft3type, &lb, &extent );
76     MPI_Type_size( ft3type, &typesize );
77
78     MPI_Pack_size( 1, ft3type, MPI_COMM_WORLD, &packsize );
79
80     inbuf   = (char *)malloc( extent );
81     outbuf  = (char *)malloc( packsize );
82     outbuf2 = (char *)malloc( packsize );
83     if (!inbuf) {
84         fprintf( stderr, "Unable to allocate %ld for inbuf\n", (long)extent );
85         MPI_Abort( MPI_COMM_WORLD, 1 );
86     }
87     if (!outbuf) {
88         fprintf( stderr, "Unable to allocate %ld for outbuf\n", (long)packsize );
89         MPI_Abort( MPI_COMM_WORLD, 1 );
90     }
91     if (!outbuf2) {
92         fprintf( stderr, "Unable to allocate %ld for outbuf2\n", (long)packsize );
93         MPI_Abort( MPI_COMM_WORLD, 1 );
94     }
95     for (i=0; i<extent; i++) {
96         inbuf[i] = i & 0x7f;
97     }
98     position = 0;
99     /* Warm up the code and data */
100     MPI_Pack( inbuf, 1, ft3type, outbuf, packsize, &position, MPI_COMM_WORLD );
101
102     /* Pack using the vector of vector of contiguous */
103     tpack = 1e12;
104     for (ntry = 0; ntry < 5; ntry++) {
105         position = 0;
106         t0 = MPI_Wtime();
107         MPI_Pack( inbuf, 1, ft3type, outbuf, packsize, &position, 
108                   MPI_COMM_WORLD );
109         t1 = MPI_Wtime() - t0;
110         if (t1 < tpack) tpack = t1;
111     }
112     MPI_Type_free( &ft3type );
113
114     /* Pack using vector of vector with big blocks (same type map) */
115     tpackopt = 1e12;
116     for (ntry = 0; ntry < 5; ntry++) {
117         position = 0;
118         t0 = MPI_Wtime();
119         MPI_Pack( inbuf, 1, ftopttype, outbuf, packsize, &position, 
120                   MPI_COMM_WORLD );
121         t1 = MPI_Wtime() - t0;
122         if (t1 < tpackopt) tpackopt = t1;
123     }
124     MPI_Type_free( &ftopttype );
125
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.
130     */
131     tmanual = 1e12;
132     for (ntry = 0; ntry < 5; ntry++) {
133         const char *ppe = (const char *)inbuf;
134         int k, j;
135         t0 = MPI_Wtime();
136         position = 0;
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 );
141                 ptr      += vstride * 24;
142                 position += 24*vblock;
143             }
144             ppe += v2stride;
145         }
146         t1 = MPI_Wtime() - t0;
147         if (t1 < tmanual) tmanual = t1;
148
149         /* Check on correctness */
150 #ifdef PACK_IS_NATIVE
151         if (memcmp( outbuf, outbuf2, position ) != 0) {
152             printf( "Panic - pack buffers differ\n" );
153         }
154 #endif
155     }
156
157     if (verbose) {
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 );
161     }
162
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) {
166         errs++;
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" );
170     }
171     if (4 * tmanual < tpackopt) {
172         errs++;
173         printf( "MPI_Pack with opt = %e, manual pack time = %e\n", tpackopt, 
174                 tmanual );
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" );
177     }
178     if (errs) {
179         printf( " Found %d errors\n", errs );
180     }
181     else {
182         printf( " No Errors\n" );
183     } 
184     
185     free( inbuf );
186     free( outbuf );
187     free( outbuf2 );
188
189     MPI_Finalize();
190     return 0;
191 }