Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'mc'
[simgrid.git] / teshsuite / smpi / mpich3-test / perf / indexperf.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 indexed datatypes.
9  *
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.
12  */
13
14 #ifdef MPICH
15 /* MPICH (as of 6/2012) packs the native bytes */
16 #define PACK_IS_NATIVE
17 #endif
18
19 #include "mpi.h"
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 static int verbose = 0;
25
26 int main( int argc, char **argv )
27 {
28     double       *inbuf, *outbuf, *outbuf2;
29     MPI_Aint     lb, extent;
30     int          *index_displacement;
31     int          icount, errs=0;
32     int          i, packsize, position, inbufsize;
33     MPI_Datatype itype1, stype1;
34     double       t0, t1;
35     double       tpack, tspack, tmanual;
36     int          ntry;
37
38     MPI_Init( &argc, &argv );
39
40     icount = 2014;
41
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",
46                  icount );
47         MPI_Abort( MPI_COMM_WORLD, 1 );
48     }
49
50     for (i=0; i<icount; i++) {
51         index_displacement[i] = (i * 3 + (i%3));
52     }
53
54     MPI_Type_create_indexed_block( icount, 1, index_displacement, MPI_DOUBLE, 
55                                    &itype1 );
56     MPI_Type_commit( &itype1 );
57     
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 */
61     if (verbose) {
62         printf( "Block index datatype:\n" );
63         MPIDU_Datatype_debug( itype1, 10 );
64     }
65 #endif
66     MPI_Type_get_extent( itype1, &lb, &extent );
67
68     MPI_Pack_size( 1, itype1, MPI_COMM_WORLD, &packsize );
69
70     inbufsize = extent / sizeof(double);
71
72     inbuf   = (double *)malloc( extent );
73     outbuf  = (double *)malloc( packsize );
74     outbuf2 = (double *)malloc( icount * sizeof(double) );
75     if (!inbuf) {
76         fprintf( stderr, "Unable to allocate %ld for inbuf\n", (long)extent );
77         MPI_Abort( MPI_COMM_WORLD, 1 );
78     }
79     if (!outbuf) {
80         fprintf( stderr, "Unable to allocate %ld for outbuf\n", (long)packsize );
81         MPI_Abort( MPI_COMM_WORLD, 1 );
82     }
83     if (!outbuf2) {
84         fprintf( stderr, "Unable to allocate %ld for outbuf2\n", (long)packsize );
85         MPI_Abort( MPI_COMM_WORLD, 1 );
86     }
87     for (i=0; i<inbufsize; i++) {
88         inbuf[i] = (double)i;
89     }
90     position = 0;
91     /* Warm up the code and data */
92     MPI_Pack( inbuf, 1, itype1, outbuf, packsize, &position, MPI_COMM_WORLD );
93
94     tpack = 1e12;
95     for (ntry = 0; ntry < 5; ntry++) {
96         position = 0;
97         t0 = MPI_Wtime();
98         MPI_Pack( inbuf, 1, itype1, outbuf, packsize, &position, 
99                   MPI_COMM_WORLD );
100         t1 = MPI_Wtime() - t0;
101         if (t1 < tpack) tpack = t1;
102     }
103
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 );
107     }
108
109     position = 0;
110     /* Warm up the code and data */
111     MPI_Pack( MPI_BOTTOM, 1, stype1, outbuf, packsize, &position, MPI_COMM_WORLD );
112
113     tspack = 1e12;
114     for (ntry = 0; ntry < 5; ntry++) {
115         position = 0;
116         t0 = MPI_Wtime();
117         MPI_Pack( MPI_BOTTOM, 1, stype1, outbuf, packsize, &position, 
118                   MPI_COMM_WORLD );
119         t1 = MPI_Wtime() - t0;
120         if (t1 < tspack) tspack = t1;
121     }
122
123     /* 
124        Simple manual pack (without explicitly unrolling the index block)
125     */
126     tmanual = 1e12;
127     for (ntry = 0; ntry < 5; ntry++) {
128         const double *ppe = (const double *)inbuf;
129         const int    *id  = (const int *)index_displacement;
130         int k, j;
131         t0 = MPI_Wtime();
132         position = 0;
133         for (i=0; i<icount; i++) { 
134             outbuf2[position++] = ppe[id[i]];
135         }
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" );
142         }
143 #endif
144     }
145
146     if (verbose) {
147         printf( "Bytes packed = %d\n", position );
148         printf( "MPI_Pack time = %e, manual pack time = %e\n", 
149                 tpack, tmanual );
150         printf( "Pack with struct = %e\n", tspack );
151     }
152
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) {
158         errs++;
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" );
162     }
163     if (2 * tmanual < tspack) {
164         errs++;
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" );
168     }
169     if (errs) {
170         printf( " Found %d errors\n", errs );
171     }
172     else {
173         printf( " No Errors\n" );
174     } 
175
176     MPI_Type_free( &itype1 );
177     MPI_Type_free( &stype1 );
178     
179     free( inbuf );
180     free( outbuf );
181     free( outbuf2 );
182     free( index_displacement );
183
184     MPI_Finalize();
185     return 0;
186 }