Statistiques
| Révision :

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

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

1
//
2
// Estimation of Pi using Monte Carlo exploration process
3
// gcc -std=c99 -O3 -o Pi_aMPI Pi_aMPI.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
#include <stddef.h>
16

    
17
#include <sys/time.h>
18

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

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

    
32
#define ITERATIONS 1000000000
33

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

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

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

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

    
69
  LENGTH total=0;
70

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

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

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

    
142
}
143

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

    
146
  unsigned int seed_z=362436069,seed_w=52128862;
147
  LENGTH iterations=ITERATIONS,inside[8192],insides,part_inside,part_iterations;
148
  int numtasks,rank,rc,tag=1,i;
149
  float pi;
150

    
151
  char hostname[128];
152

    
153
  gethostname(hostname, sizeof hostname);
154

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

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

    
169
  MPI_Comm_size(MPI_COMM_WORLD,&numtasks);
170
  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
171
  
172
  MPI_Comm_size(MPI_COMM_WORLD,&numtasks);
173
  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
174

    
175
  const int nitems=2;
176
  int blocklengths[2] = {1,1};
177

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

    
184
  MPI_Datatype mpi_result_type;
185
  MPI_Aint     offsets[2];
186

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

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

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

    
246
        if (numtasks>1) {
247
            MPI_Wait(&RequestRecv2, &Stat);
248
        }
249
        
250
        inside[i]=recv.inside;
251
        useconds=recv.useconds;
252
        
253
        printf("\tReceive from %i, find %lld inside in %lu useconds\n",i,(long long)inside[i],useconds);
254
        
255
        insides+=inside[i];
256
      }
257
      
258
      pi=4.*(float)insides/(float)(part_iterations*numtasks);
259
      
260
      printf("\n\tPi=%.40f\n\twith error %.40f\n\twith %lld iterations\n\n",pi,
261
             fabs(pi-4*atan(1.))/pi,(long long)iterations);
262

    
263
  }
264
  else
265
    {
266
      // Receive information from master
267
      
268
#ifdef LONG
269
      rc = MPI_Irecv(&part_iterations, 1, MPI_LONG_LONG, 0, tag, 
270
                    MPI_COMM_WORLD, &RequestRecv);
271
#else
272
      rc = MPI_Irecv(&part_iterations, 1, MPI_INT, 0, tag, 
273
                    MPI_COMM_WORLD, &RequestRecv);
274
#endif
275
      MPI_Wait(&RequestRecv, &Stat);
276
      
277
      /* Not such a good idea to print information... 
278
         printf("\tOn %s with rank %i, receive from master %lld\n",
279
         hostname,rank,(long long)part_iterations); */
280
      
281
      gettimeofday(&start,(struct timezone *)0);
282

    
283
      part_inside=MainLoopGlobal(part_iterations,rotr(seed_w,rank),rotl(seed_z,rank));
284
      
285
      gettimeofday(&end,(struct timezone *)0);
286
      useconds=(end.tv_sec-start.tv_sec)*1000000+end.tv_usec-start.tv_usec;
287

    
288
      /*
289
      printf("\tOn %s with rank %i, find %lld inside in %lu useconds.\n",
290
             hostname,rank,(long long)part_inside,useconds);
291
      */
292

    
293
      result send;
294
      send.inside=part_inside;
295
      send.useconds=useconds;      
296
      
297
      rc = MPI_Isend(&send, 1, mpi_result_type, 0, tag, MPI_COMM_WORLD,&RequestSend2);
298

    
299
      MPI_Wait(&RequestSend2, &Stat);
300

    
301
    }
302

    
303
  MPI_Type_free(&mpi_result_type);
304
  MPI_Finalize();
305
  
306
}