Statistiques
| Révision :

root / Pi / C / MPI / Pi_aMPI.c @ 283

Historique | Voir | Annoter | Télécharger (8,49 ko)

1
//
2
// Estimation of Pi using Monte Carlo exploration process
3
// Cecill v2 Emmanuel QUEMENER <emmanuel.quemener@gmail.com>
4
// gcc -std=c99 -O3 -o Pi_aMPI Pi_aMPI.c -lm 
5

    
6
// Needed for gethostname
7
#define _DEFAULT_SOURCE
8
#include <sys/unistd.h>
9

    
10
#include <math.h>
11
#include <stdio.h>
12
#include <stdlib.h>
13
#include <limits.h>
14
#include <mpi.h>
15
#include <stddef.h>
16
#include <sys/time.h>
17

    
18
// Marsaglia RNG very simple implementation
19
#define znew  ((z=36969*(z&65535)+(z>>16))<<16)
20
#define wnew  ((w=18000*(w&65535)+(w>>16))&65535)
21
#define MWC   (znew+wnew)
22
#define SHR3  (jsr=(jsr=(jsr=jsr^(jsr<<17))^(jsr>>13))^(jsr<<5))
23
#define CONG  (jcong=69069*jcong+1234567)
24
#define KISS  ((MWC^CONG)+SHR3)
25

    
26
#define MWCfp MWC * 2.328306435454494e-10f
27
#define KISSfp KISS * 2.328306435454494e-10f
28
#define SHR3fp SHR3 * 2.328306435454494e-10f
29
#define CONGfp CONG * 2.328306435454494e-10f
30

    
31
#define ITERATIONS 1000000000
32

    
33
#ifdef LONG
34
#define LENGTH long long
35
#else
36
#define LENGTH int
37
#endif
38

    
39
typedef struct compute_node {
40
        LENGTH inside;
41
        long int useconds;
42
} result;
43

    
44
unsigned int rotl(unsigned int value, int shift) {
45
    return (value << shift) | (value >> (sizeof(value) * CHAR_BIT - shift));
46
}
47
 
48
unsigned int rotr(unsigned int value, int shift) {
49
    return (value >> shift) | (value << (sizeof(value) * CHAR_BIT - shift));
50
}
51

    
52
LENGTH MainLoopGlobal(LENGTH iterations,unsigned int seed_w,unsigned int seed_z)
53
{
54
#if defined TCONG
55
   unsigned int jcong=seed_z;
56
#elif defined TSHR3
57
   unsigned int jsr=seed_w;
58
#elif defined TMWC
59
   unsigned int z=seed_z;
60
   unsigned int w=seed_w;
61
#elif defined TKISS
62
   unsigned int jcong=seed_z;
63
   unsigned int jsr=seed_w;
64
   unsigned int z=seed_z;
65
   unsigned int w=seed_w;
66
#endif
67

    
68
  LENGTH total=0;
69

    
70
   for (LENGTH i=0;i<iterations;i++) {
71

    
72
#if defined TINT32
73
    #define THEONE 1073741824
74
    #if defined TCONG
75
        unsigned int x=CONG>>17 ;
76
        unsigned int y=CONG>>17 ;
77
    #elif defined TSHR3
78
        unsigned int x=SHR3>>17 ;
79
        unsigned int y=SHR3>>17 ;
80
    #elif defined TMWC
81
        unsigned int x=MWC>>17 ;
82
        unsigned int y=MWC>>17 ;
83
    #elif defined TKISS
84
        unsigned int x=KISS>>17 ;
85
        unsigned int y=KISS>>17 ;
86
    #endif
87
#elif defined TINT64
88
    #define THEONE 4611686018427387904
89
    #if defined TCONG
90
        unsigned long x=(unsigned long)(CONG>>1) ;
91
        unsigned long y=(unsigned long)(CONG>>1) ;
92
    #elif defined TSHR3
93
        unsigned long x=(unsigned long)(SHR3>>1) ;
94
        unsigned long y=(unsigned long)(SHR3>>1) ;
95
    #elif defined TMWC
96
        unsigned long x=(unsigned long)(MWC>>1) ;
97
        unsigned long y=(unsigned long)(MWC>>1) ;
98
    #elif defined TKISS
99
        unsigned long x=(unsigned long)(KISS>>1) ;
100
        unsigned long y=(unsigned long)(KISS>>1) ;
101
    #endif
102
#elif defined TFP32
103
    #define THEONE 1.0f
104
    #if defined TCONG
105
        float x=CONGfp ;
106
        float y=CONGfp ;
107
    #elif defined TSHR3
108
        float x=SHR3fp ;
109
        float y=SHR3fp ;
110
    #elif defined TMWC
111
        float x=MWCfp ;
112
        float y=MWCfp ;
113
    #elif defined TKISS
114
      float x=KISSfp ;
115
      float y=KISSfp ;
116
    #endif
117
#elif defined TFP64
118
    #define THEONE 1.0f
119
    #if defined TCONG
120
        double x=(double)CONGfp ;
121
        double y=(double)CONGfp ;
122
    #elif defined TSHR3
123
        double x=(double)SHR3fp ;
124
        double y=(double)SHR3fp ;
125
    #elif defined TMWC
126
        double x=(double)MWCfp ;
127
        double y=(double)MWCfp ;
128
    #elif defined TKISS
129
        double x=(double)KISSfp ;
130
        double y=(double)KISSfp ;
131
    #endif
132
#endif
133

    
134
      // Matching test
135
      unsigned long inside=((x*x+y*y) < THEONE) ? 1:0;
136
      total+=inside;
137
   }
138
  
139
   return(total);
140

    
141
}
142

    
143
int main(int argc, char *argv[]) {
144

    
145
  unsigned int seed_z=362436069,seed_w=52128862;
146
  LENGTH iterations=ITERATIONS,inside[8192],insides,part_inside,part_iterations;
147
  int NumberProcesses,rank,rc,tag=1,i;
148

    
149
  char hostname[128];
150

    
151
  gethostname(hostname, sizeof hostname);
152

    
153
#ifdef TIME
154
  struct timeval start,end;
155
  long int useconds;
156
#endif
157

    
158
  MPI_Status Stat;
159
  MPI_Request RequestSend, RequestRecv, RequestSend2, RequestRecv2;
160
     
161
  rc = MPI_Init(&argc,&argv);
162
  if (rc != MPI_SUCCESS) {
163
    printf ("Error starting MPI program. Terminating.\n");
164
    MPI_Abort(MPI_COMM_WORLD, rc);
165
  }
166

    
167
  MPI_Comm_size(MPI_COMM_WORLD,&NumberProcesses);
168
  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
169
  
170
  MPI_Comm_size(MPI_COMM_WORLD,&NumberProcesses);
171
  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
172

    
173
  const int nitems=2;
174
  int blocklengths[2] = {1,1};
175

    
176
#ifdef LONG
177
  MPI_Datatype types[2] = {MPI_LONG, MPI_LONG};
178
#else
179
  MPI_Datatype types[2] = {MPI_INT, MPI_LONG};
180
#endif
181

    
182
  MPI_Datatype mpi_result_type;
183
  MPI_Aint     offsets[2];
184

    
185
  offsets[0] = offsetof(result, inside);
186
  offsets[1] = offsetof(result, useconds);
187
  
188
  MPI_Type_create_struct(nitems, blocklengths, offsets, types, &mpi_result_type);
189
  MPI_Type_commit(&mpi_result_type);
190

    
191
  if (rank==0) {
192

    
193
    struct timeval tv1,tv2;
194
    
195
    if (argc > 1) {
196
      iterations=(LENGTH)atoll(argv[1]);
197
    }
198
    else {
199
      printf("\n\tPi : Estimate Pi with Monte Carlo exploration\n\n");
200
      printf("\t\t#1 : number of iterations (default 1 billion)\n\n");
201
    }
202
    
203
    printf ("\tSizeof int = %lld bytes.\n", (long long)sizeof(int));
204
    printf ("\tSizeof long = %lld bytes.\n", (long long)sizeof(long));
205
    printf ("\tSizeof long long = %lld bytes.\n", (long long)sizeof(long long));
206
    
207
    printf ("\tMax int = %u\n", INT_MAX);
208
    printf ("\tMax long = %ld\n", LONG_MAX);
209
    printf ("\tMax long long = %lld\n\n", LLONG_MAX);
210
    
211
    part_iterations=((iterations%NumberProcesses) == 0) ? iterations/NumberProcesses:iterations/NumberProcesses+1 ;
212

    
213
    gettimeofday(&tv1, NULL);
214
    
215
    // Split part of code
216
    for (i=1;i<NumberProcesses;i++) {
217
      
218
#ifdef LONG
219
      rc = MPI_Isend(&part_iterations, 1, MPI_LONG_LONG, i, tag, 
220
                     MPI_COMM_WORLD,&RequestSend);
221
#else
222
      rc = MPI_Isend(&part_iterations, 1, MPI_INT, i, tag, 
223
                     MPI_COMM_WORLD,&RequestSend);
224
#endif      
225
    }
226
    if (NumberProcesses>1) {
227
      MPI_Wait(&RequestSend, &Stat);
228
    }
229
    
230
    gettimeofday(&start,(struct timezone *)0);
231
    
232
    insides=MainLoopGlobal(part_iterations,seed_w,seed_z);
233
    
234
    gettimeofday(&end,(struct timezone *)0);
235
    useconds=(end.tv_sec-start.tv_sec)*1000000+end.tv_usec-start.tv_usec;
236
    
237
    printf("\tOn %s with rank %i, find %lld inside in %lu useconds.\n",
238
             hostname,rank,(long long)insides,useconds);
239
      
240
    // Join part of code
241
      for (i=1;i<NumberProcesses;i++) {
242

    
243
        result recv;
244
        
245
        rc = MPI_Irecv(&recv, 1, mpi_result_type, i, tag, 
246
                      MPI_COMM_WORLD, &RequestRecv2);
247

    
248
        if (NumberProcesses>1) {
249
            MPI_Wait(&RequestRecv2, &Stat);
250
        }
251
        
252
        inside[i]=recv.inside;
253
        useconds=recv.useconds;
254
        
255
        printf("\tReceive from %i, find %lld inside in %lu useconds\n",i,(long long)inside[i],useconds);
256
        
257
        insides+=inside[i];
258
      }
259
      
260
      gettimeofday(&tv2, NULL);
261
      
262
      double elapsed=(double)((tv2.tv_sec-tv1.tv_sec) * 1000000L +
263
                              (tv2.tv_usec-tv1.tv_usec))/1000000;
264
      
265
      double itops=(double)(part_iterations*NumberProcesses)/elapsed;
266
  
267
      printf("\nParallelRate %i\nElapsed Time %.2f\nItops %.0f\nLogItops %.2f\n",NumberProcesses,elapsed,itops,log10(itops));
268

    
269
      LENGTH total=((iterations%NumberProcesses)==0)?iterations:(iterations/NumberProcesses+1)*NumberProcesses;
270

    
271
      printf("Inside/Total %ld %ld\nPi estimation %f\n\n",(long int)insides,(long int)total,(4.*(float)insides/total));
272
      
273
  }
274
  else
275
    {
276
      // Receive information from master
277
      
278
#ifdef LONG
279
      rc = MPI_Irecv(&part_iterations, 1, MPI_LONG_LONG, 0, tag, 
280
                    MPI_COMM_WORLD, &RequestRecv);
281
#else
282
      rc = MPI_Irecv(&part_iterations, 1, MPI_INT, 0, tag, 
283
                    MPI_COMM_WORLD, &RequestRecv);
284
#endif
285
      MPI_Wait(&RequestRecv, &Stat);
286
      
287
      /* Not such a good idea to print information... 
288
         printf("\tOn %s with rank %i, receive from master %lld\n",
289
         hostname,rank,(long long)part_iterations); */
290
      
291
      gettimeofday(&start,(struct timezone *)0);
292

    
293
      part_inside=MainLoopGlobal(part_iterations,rotr(seed_w,rank),rotl(seed_z,rank));
294
      
295
      gettimeofday(&end,(struct timezone *)0);
296
      useconds=(end.tv_sec-start.tv_sec)*1000000+end.tv_usec-start.tv_usec;
297

    
298
      /*
299
      printf("\tOn %s with rank %i, find %lld inside in %lu useconds.\n",
300
             hostname,rank,(long long)part_inside,useconds);
301
      */
302

    
303
      result send;
304
      send.inside=part_inside;
305
      send.useconds=useconds;      
306
      
307
      rc = MPI_Isend(&send, 1, mpi_result_type, 0, tag, MPI_COMM_WORLD,&RequestSend2);
308

    
309
      MPI_Wait(&RequestSend2, &Stat);
310

    
311
    }
312

    
313
  MPI_Type_free(&mpi_result_type);
314
  MPI_Finalize();
315
  
316
}