Statistiques
| Révision :

root / Pi / C / MPI / Pi_MPI.c @ 246

Historique | Voir | Annoter | Télécharger (7,56 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
#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
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 numtasks,rank,rc,tag=1,i;
148
  float pi;
149

    
150
  char hostname[128];
151

    
152
  gethostname(hostname, sizeof hostname);
153

    
154
  struct timeval start,end;
155
  long int useconds;
156

    
157
  MPI_Status Stat;
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
  const int nitems=2;
169
  int blocklengths[2] = {1,1};
170

    
171
#ifdef LONG
172
  MPI_Datatype types[2] = {MPI_LONG, MPI_LONG};
173
#else
174
  MPI_Datatype types[2] = {MPI_INT, MPI_LONG};
175
#endif
176

    
177
  MPI_Datatype mpi_result_type;
178
  MPI_Aint     offsets[2];
179

    
180
  offsets[0] = offsetof(result, inside);
181
  offsets[1] = offsetof(result, useconds);
182
  
183
  MPI_Type_create_struct(nitems, blocklengths, offsets, types, &mpi_result_type);
184
  MPI_Type_commit(&mpi_result_type);
185
    
186
  if (rank==0) {
187
    
188
    if (argc > 1) {
189
      iterations=(LENGTH)atoll(argv[1]);
190
    }
191
    else {
192
      printf("\n\tPi : Estimate Pi with Monte Carlo exploration\n\n");
193
      printf("\t\t#1 : number of iterations (default 1 billion)\n\n");
194
    }
195
    
196
    printf ("\tSizeof int = %lld bytes.\n", (long long)sizeof(int));
197
    printf ("\tSizeof long = %lld bytes.\n", (long long)sizeof(long));
198
    printf ("\tSizeof long long = %lld bytes.\n", (long long)sizeof(long long));
199
    
200
    printf ("\tMax int = %u\n", INT_MAX);
201
    printf ("\tMax long = %ld\n", LONG_MAX);
202
    printf ("\tMax long long = %lld\n\n", LLONG_MAX);
203
    
204
    part_iterations=((iterations%numtasks) == 0) ? iterations/numtasks:iterations/numtasks+1 ;
205
    
206
    // Split part of code
207
    for (i=1;i<numtasks;i++) {
208
      
209
#ifdef LONG
210
      rc = MPI_Send(&part_iterations, 1, MPI_LONG_LONG, i, tag, 
211
                    MPI_COMM_WORLD);
212
#else
213
      rc = MPI_Send(&part_iterations, 1, MPI_INT, i, tag, 
214
                    MPI_COMM_WORLD);
215
#endif
216
    }
217
    
218
    gettimeofday(&start,(struct timezone *)0);
219
    
220
    insides=MainLoopGlobal(part_iterations,seed_w,seed_z);
221
    
222
    gettimeofday(&end,(struct timezone *)0);
223
    useconds=(end.tv_sec-start.tv_sec)*1000000+end.tv_usec-start.tv_usec;
224
    
225
    printf("\tOn %s with rank %i, find %lld inside in %lu useconds.\n",
226
             hostname,rank,(long long)insides,useconds);
227
      
228
    // Join part of code
229
      for (i=1;i<numtasks;i++) {
230

    
231
        result recv;
232
        
233
        rc = MPI_Recv(&recv, 1, mpi_result_type, i, tag, 
234
                      MPI_COMM_WORLD, &Stat);
235

    
236
        inside[i]=recv.inside;
237
        useconds=recv.useconds;
238
        
239
        printf("\tReceive from %i, find %lld inside in %lu useconds\n",i,(long long)inside[i],useconds);
240
        
241
        insides+=inside[i];
242
      }
243
      
244
      pi=4.*(float)insides/(float)(part_iterations*numtasks);
245
      
246
      printf("\n\tPi=%.40f\n\twith error %.40f\n\twith %lld iterations\n\n",pi,
247
             fabs(pi-4*atan(1.))/pi,(long long)iterations);
248

    
249
  }
250
  else
251
    {
252
      // Receive information from master
253
#ifdef LONG
254
      rc = MPI_Recv(&part_iterations, 1, MPI_LONG_LONG, 0, tag, 
255
                    MPI_COMM_WORLD, &Stat);
256
#else
257
      rc = MPI_Recv(&part_iterations, 1, MPI_INT, 0, tag, 
258
                    MPI_COMM_WORLD, &Stat);
259
#endif
260
      
261
      /*      Not such a good idea to print information... 
262
              printf("\tOn %s with rank %i, receive from master %lld\n",
263
              hostname,rank,(long long)part_iterations); */
264
      
265
      gettimeofday(&start,(struct timezone *)0);
266

    
267
      part_inside=MainLoopGlobal(part_iterations,rotr(seed_w,rank),rotl(seed_z,rank));
268
      
269
      gettimeofday(&end,(struct timezone *)0);
270
      useconds=(end.tv_sec-start.tv_sec)*1000000+end.tv_usec-start.tv_usec;
271

    
272
      /*      
273
      printf("\tOn %s with rank %i, find %lld inside in %lu useconds.\n",
274
             hostname,rank,(long long)part_inside,useconds);
275
      */
276

    
277
      result send;
278
      send.inside=part_inside;
279
      send.useconds=useconds;
280

    
281
      rc = MPI_Send(&send, 1, mpi_result_type, 0, tag, MPI_COMM_WORLD);
282

    
283
    }
284

    
285
  MPI_Type_free(&mpi_result_type);  
286
  MPI_Finalize();
287
}