Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add new entry in Release_Notes.
[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", icount);
46         MPI_Abort(MPI_COMM_WORLD, 1);
47     }
48
49     for (i = 0; i < icount; i++) {
50         index_displacement[i] = (i * 3 + (i % 3));
51     }
52
53     MPI_Type_create_indexed_block(icount, 1, index_displacement, MPI_DOUBLE, &itype1);
54     MPI_Type_commit(&itype1);
55
56 #if defined(MPICH) && defined(PRINT_DATATYPE_INTERNALS)
57     /* To use MPIDU_Datatype_debug to print the datatype internals,
58      * you must configure MPICH with --enable-g=log */
59     if (verbose) {
60         printf("Block index datatype:\n");
61         MPIDU_Datatype_debug(itype1, 10);
62     }
63 #endif
64     MPI_Type_get_extent(itype1, &lb, &extent);
65
66     MPI_Pack_size(1, itype1, MPI_COMM_WORLD, &packsize);
67
68     inbufsize = extent / sizeof(double);
69
70     inbuf = (double *) malloc(extent);
71     outbuf = (double *) malloc(packsize);
72     outbuf2 = (double *) malloc(icount * sizeof(double));
73     if (!inbuf) {
74         fprintf(stderr, "Unable to allocate %ld for inbuf\n", (long) extent);
75         MPI_Abort(MPI_COMM_WORLD, 1);
76     }
77     if (!outbuf) {
78         fprintf(stderr, "Unable to allocate %ld for outbuf\n", (long) packsize);
79         MPI_Abort(MPI_COMM_WORLD, 1);
80     }
81     if (!outbuf2) {
82         fprintf(stderr, "Unable to allocate %ld for outbuf2\n", (long) packsize);
83         MPI_Abort(MPI_COMM_WORLD, 1);
84     }
85     for (i = 0; i < inbufsize; i++) {
86         inbuf[i] = (double) i;
87     }
88     position = 0;
89     /* Warm up the code and data */
90     MPI_Pack(inbuf, 1, itype1, outbuf, packsize, &position, MPI_COMM_WORLD);
91
92     tpack = 1e12;
93     for (ntry = 0; ntry < 5; ntry++) {
94         position = 0;
95         t0 = MPI_Wtime();
96         MPI_Pack(inbuf, 1, itype1, outbuf, packsize, &position, MPI_COMM_WORLD);
97         t1 = MPI_Wtime() - t0;
98         if (t1 < tpack)
99             tpack = t1;
100     }
101
102     {
103         int one = 1;
104         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, MPI_COMM_WORLD);
118         t1 = MPI_Wtime() - t0;
119         if (t1 < tspack)
120             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         t0 = MPI_Wtime();
131         position = 0;
132         for (i = 0; i < icount; i++) {
133             outbuf2[position++] = ppe[id[i]];
134         }
135         t1 = MPI_Wtime() - t0;
136         if (t1 < tmanual)
137             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", tpack, tmanual);
149         printf("Pack with struct = %e\n", tspack);
150     }
151
152     /* The threshold here permits the MPI datatype to perform at up to
153      * only one half the performance of simple user code.  Note that the
154      * example code above may be made faster through careful use of const,
155      * restrict, and unrolling if the compiler doesn't already do that. */
156     if (2 * tmanual < tpack) {
157         errs++;
158         printf("MPI_Pack (block index) time = %e, manual pack time = %e\n", tpack, tmanual);
159         printf("MPI_Pack time should be less than 2 times the manual time\n");
160         printf("For most informative results, be sure to compile this test with optimization\n");
161     }
162     if (2 * tmanual < tspack) {
163         errs++;
164         printf("MPI_Pack (struct of block index)) time = %e, manual pack time = %e\n", tspack,
165                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 }