Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
c54400f7d4be16bc775c3c790c2fc97d8ea5b26c
[simgrid.git] / teshsuite / smpi / mpich3-test / perf / nestvec2.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 the performance of a struct that contains a vector type
9  * exploits the vector type correctly
10  *
11  * If PACK_IS_NATIVE is defined, MPI_Pack stores exactly the same bytes as the
12  * user would pack manually; in that case, there is a consistency check.
13  */
14
15 #include "mpi.h"
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19
20 #include "mpitestconf.h"
21 #ifdef HAVE_STDINT_H
22 #include <stdint.h>
23 #endif
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, vstride;
36     int32_t      counts[2];
37     int          v2stride, typesize, packsize, i, position, errs = 0;
38     double       *outbuf, *outbuf2;
39     double       *vsource;
40     MPI_Datatype vtype, stype;
41     MPI_Aint     lb, extent;
42     double       t0, t1;
43     double       tspack, tvpack, tmanual;
44     int          ntry;
45     int          blocklengths[2];
46     MPI_Aint     displacements[2];
47     MPI_Datatype typesArray[2];
48
49     MPI_Init( &argc, &argv );
50     
51     /* Create a struct consisting of a two 32-bit ints, followed by a 
52        vector of stride 3 but count 128k (less than a few MB of data area) */
53     vcount  = 128000;
54     vstride = 3;
55     MPI_Type_vector( vcount, 1, vstride, MPI_DOUBLE, &vtype );
56
57     vsource = (double *)malloc( (vcount + 1) * (vstride + 1) * sizeof(double) );
58     if (!vsource) {
59         fprintf( stderr, "Unable to allocate vsource\n" );
60         MPI_Abort( MPI_COMM_WORLD, 1 );
61     }
62     for (i=0; i<vcount*vstride; i++) {
63         vsource[i] = i;
64     }
65     blocklengths[0] = 2; MPI_Get_address( &counts[0], &displacements[0] );
66     blocklengths[1] = 1; MPI_Get_address( vsource, &displacements[1] );
67     if (verbose) {
68         printf( "%p = %p?\n", vsource, (void *)displacements[1] );
69     }
70     typesArray[0] = MPI_INT32_T;
71     typesArray[1] = vtype;
72     MPI_Type_create_struct( 2, blocklengths, displacements, typesArray, 
73                             &stype );
74     MPI_Type_commit( &stype );
75     MPI_Type_commit( &vtype );
76
77 #if defined(MPICH) && defined(PRINT_DATATYPE_INTERNALS)
78     /* To use MPIDU_Datatype_debug to print the datatype internals,
79        you must configure MPICH with --enable-g=log */
80     if (verbose) {
81         printf( "Original struct datatype:\n" );
82         MPIDU_Datatype_debug( stype, 10 );
83     }
84 #endif
85
86     MPI_Pack_size( 1, stype, MPI_COMM_WORLD, &packsize );
87     outbuf  = (double *)malloc( packsize );
88     outbuf2 = (double *)malloc( packsize );
89     if (!outbuf) {
90         fprintf( stderr, "Unable to allocate %ld for outbuf\n", (long)packsize );
91         MPI_Abort( MPI_COMM_WORLD, 1 );
92     }
93     if (!outbuf2) {
94         fprintf( stderr, "Unable to allocate %ld for outbuf2\n", (long)packsize );
95         MPI_Abort( MPI_COMM_WORLD, 1 );
96     }
97     position = 0;
98     /* Warm up the code and data */
99     MPI_Pack( MPI_BOTTOM, 1, stype, outbuf, packsize, &position, 
100               MPI_COMM_WORLD );
101
102     tspack = 1e12;
103     for (ntry = 0; ntry < 5; ntry++) {
104         position = 0;
105         t0 = MPI_Wtime();
106         MPI_Pack( MPI_BOTTOM, 1, stype, outbuf, packsize, &position, 
107                   MPI_COMM_WORLD );
108         t1 = MPI_Wtime() - t0;
109         if (t1 < tspack) tspack = t1;
110     }
111     MPI_Type_free( &stype );
112
113     /* An equivalent packing, using the 2 ints and the vector separately */
114     tvpack = 1e12;
115     for (ntry = 0; ntry < 5; ntry++) {
116         position = 0;
117         t0 = MPI_Wtime();
118         MPI_Pack( counts, 2, MPI_INT32_T, outbuf, packsize, &position, 
119                   MPI_COMM_WORLD );
120         MPI_Pack( vsource, 1, vtype, outbuf, packsize, &position, 
121                   MPI_COMM_WORLD );
122         t1 = MPI_Wtime() - t0;
123         if (t1 < tvpack) tvpack = t1;
124     }
125     MPI_Type_free( &vtype );
126
127     /* Note that we exploit the fact that the vector type contains vblock 
128        instances of a contiguous type of size 24, or a single block of 24*vblock
129        bytes.
130     */
131     tmanual = 1e12;
132     for (ntry = 0; ntry < 5; ntry++) {
133         const double * restrict ppe = (const double *)vsource;
134         double * restrict ppo = outbuf2;
135         int j;
136         t0 = MPI_Wtime();
137         position = 0;
138         *(int32_t *)ppo          = counts[0];
139         *( ((int32_t *)ppo) + 1) = counts[1];
140         ppo++;
141         /* Some hand optimization because this file is not normally 
142            compiled with optimization by the test suite */
143         j = vcount;
144         while (j) {
145             *ppo++ = *ppe;
146             ppe += vstride;
147             *ppo++ = *ppe;
148             ppe += vstride;
149             *ppo++ = *ppe;
150             ppe += vstride;
151             *ppo++ = *ppe;
152             ppe += vstride;
153             j -= 4;
154         }
155         position += (1 + vcount);
156         position *= sizeof(double);
157         t1 = MPI_Wtime() - t0;
158         if (t1 < tmanual) tmanual = t1;
159
160         /* Check on correctness */
161 #ifdef PACK_IS_NATIVE
162         if (memcmp( outbuf, outbuf2, position ) != 0) {
163             printf( "Panic(manual) - pack buffers differ\n" );
164             for (j=0; j<8; j++) {
165                 printf( "%d: %llx\t%llx\n", j, (long long unsigned)outbuf[j], 
166                         (long long unsigned)outbuf2[j] );
167             }
168         }
169 #endif
170     }
171
172     if (verbose) {
173         printf( "Bytes packed = %d\n", position );
174         printf( "MPI_Pack time = %e (struct), = %e (vector), manual pack time = %e\n", 
175                 tspack, tvpack, tmanual );
176     }
177
178     if (4 * tmanual < tspack) {
179         errs++;
180         printf( "MPI_Pack time using struct with vector = %e, manual pack time = %e\n", tspack, tmanual )
181 ;
182         printf( "MPI_Pack time should be less than 4 times the manual time\n" );
183         printf( "For most informative results, be sure to compile this test with optimization\n" );
184     }
185     if (4 * tmanual < tvpack) {
186         errs++;
187         printf( "MPI_Pack using vector = %e, manual pack time = %e\n", tvpack, 
188                 tmanual );
189         printf( "MPI_Pack time should be less than 4 times the manual time\n" );
190         printf( "For most informative results, be sure to compile this test with optimization\n" );
191     }
192     if (4 * tvpack < tspack) {
193         errs++;
194         printf( "MPI_Pack using a vector = %e, using a struct with vector = %e\n", tvpack, tspack );
195         printf( "MPI_Pack time using vector should be about the same as the struct containing the vector\n" );
196         printf( "For most informative results, be sure to compile this test with optimization\n" );
197     }
198
199     if (errs) {
200         printf( " Found %d errors\n", errs );
201     }
202     else {
203         printf( " No Errors\n" );
204     } 
205     
206     free( vsource );
207     free( outbuf );
208     free( outbuf2 );
209
210     MPI_Finalize();
211     return 0;
212 }