Statistiques
| Révision :

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

Historique | Voir | Annoter | Télécharger (7,51 ko)

1
//
2
// Estimation of Pi using Monte Carlo exploration process
3
// gcc -std=c99 -O3 -o Pi Pi.c -lm 
4
// Emmanuel Quemener <emmanuel.quemener@ens-lyon.fr>
5

    
6
// Needed for gethostname
7
#define _BSD_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

    
16
#ifdef TIME
17
#include <sys/time.h>
18
#endif
19

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

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

    
33
#define ITERATIONS 1000000000
34

    
35
#ifdef LONG
36
#define LENGTH long long
37
#else
38
#define LENGTH int
39
#endif
40

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

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

    
65
  LENGTH total=0;
66

    
67
   for (LENGTH i=0;i<iterations;i++) {
68

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

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

    
138
}
139

    
140
int main(int argc, char *argv[]) {
141

    
142
  unsigned int seed_z=362436069,seed_w=52128862;
143
  LENGTH iterations=ITERATIONS,inside[1024],insides,part_inside,part_iterations;
144
  int numtasks,rank,rc,tag=1,i;
145
  float pi;
146

    
147
  char hostname[128];
148

    
149
  gethostname(hostname, sizeof hostname);
150

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

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

    
165
  MPI_Comm_size(MPI_COMM_WORLD,&numtasks);
166
  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
167

    
168
  if (rank==0) {
169
    
170
    if (argc > 1) {
171
      iterations=(LENGTH)atoll(argv[1]);
172
    }
173
    else {
174
      printf("\n\tPi : Estimate Pi with Monte Carlo exploration\n\n");
175
      printf("\t\t#1 : number of iterations (default 1 billion)\n\n");
176
    }
177
    
178
    printf ("Sizeof int = %lld bytes.\n", (long long)sizeof(int));
179
    printf ("Sizeof long = %lld bytes.\n", (long long)sizeof(long));
180
    printf ("Sizeof long long = %lld bytes.\n", (long long)sizeof(long long));
181
    
182
    printf ("Max int = %u\n", INT_MAX);
183
    printf ("Max long = %ld\n", LONG_MAX);
184
    printf ("Max long long = %lld\n", LLONG_MAX);
185
    
186
    part_iterations=iterations/numtasks+1;
187
    
188
    // Split part of code
189
    for (i=1;i<numtasks;i++) {
190
      
191
#ifdef LONG
192
      rc = MPI_Isend(&part_iterations, 1, MPI_LONG_LONG, i, tag, 
193
                     MPI_COMM_WORLD,&RequestSend);
194
#else
195
      rc = MPI_Isend(&part_iterations, 1, MPI_INT, i, tag, 
196
                     MPI_COMM_WORLD,&RequestSend);
197
#endif      
198
    }
199
    MPI_Wait(&RequestSend, &Stat);
200
    
201
#ifdef TIME
202
    gettimeofday(&start,(struct timezone *)0);
203
#endif
204
    
205
    insides=MainLoopGlobal(part_iterations,seed_w,seed_z);
206
    
207
#ifdef TIME
208
    gettimeofday(&end,(struct timezone *)0);
209
    useconds=(end.tv_sec-start.tv_sec)*1000000+end.tv_usec-start.tv_usec;
210
    
211
      printf("\tOn %s with rank %i, find %lld inside in %lu useconds.\n",
212
             hostname,rank,(long long)insides,useconds);
213
#else
214
      printf("\tOn %s with rank %i, find %lld inside\n",hostname,rank,
215
             (long long)insides);
216
      
217
#endif
218
      
219
    // Join part of code
220
      for (i=1;i<numtasks;i++) {
221
#ifdef LONG
222
        rc = MPI_Irecv(&inside[i], 1, MPI_LONG_LONG, i, tag, 
223
                      MPI_COMM_WORLD, &RequestRecv2);
224
#else
225
        rc = MPI_Irecv(&inside[i], 1, MPI_INT, i, tag, 
226
                      MPI_COMM_WORLD, &RequestRecv2);
227
#endif
228
        MPI_Wait(&RequestRecv2, &Stat);
229
        
230
        printf("\tReceive %lu inside from rank %i\n",(unsigned long)inside[i],i);
231
        insides+=inside[i];
232
      }
233
      
234
      pi=4.*(float)insides/(float)((iterations/numtasks)*numtasks);
235
      
236
      printf("\n\tPi=%.40f\n\twith error %.40f\n\twith %lld iterations\n\n",pi,
237
             fabs(pi-4*atan(1.))/pi,(long long)iterations);
238

    
239
  }
240
  else
241
    {
242
      // Receive information from master
243
#ifdef LONG
244
      rc = MPI_Irecv(&part_iterations, 1, MPI_LONG_LONG, 0, tag, 
245
                    MPI_COMM_WORLD, &RequestRecv);
246
#else
247
      rc = MPI_Irecv(&part_iterations, 1, MPI_INT, 0, tag, 
248
                    MPI_COMM_WORLD, &RequestRecv);
249
#endif
250
      MPI_Wait(&RequestRecv, &Stat);
251
      
252
      printf("\tOn %s with rank %i, receive from master %lld\n",
253
             hostname,rank,(long long)part_iterations);
254
      
255
#ifdef TIME
256
      gettimeofday(&start,(struct timezone *)0);
257
#endif
258

    
259
      part_inside=MainLoopGlobal(part_iterations,rotr(seed_w,rank),rotl(seed_z,rank));
260
      
261
      
262
#ifdef TIME
263
      gettimeofday(&end,(struct timezone *)0);
264
      useconds=(end.tv_sec-start.tv_sec)*1000000+end.tv_usec-start.tv_usec;
265
      
266
      printf("\tOn %s with rank %i, find %lld inside in %lu useconds.\n",
267
             hostname,rank,(long long)part_inside,useconds);
268
#else
269
      printf("\tOn %s with rank %i, find %lld inside\n",hostname,rank,
270
             (long long)part_inside);
271
      
272
#endif
273
      
274
#ifdef LONG
275
      rc = MPI_Isend(&part_inside, 1, MPI_LONG_LONG, 0, tag, MPI_COMM_WORLD,&RequestSend2);
276
#else
277
      rc = MPI_Isend(&part_inside, 1, MPI_INT, 0, tag, MPI_COMM_WORLD,&RequestSend2);
278
#endif
279
      MPI_Wait(&RequestSend2, &Stat);
280

    
281
    }
282
  
283
  MPI_Finalize();
284
  
285
}