Statistiques
| Révision :

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

Historique | Voir | Annoter | Télécharger (5,21 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

    
31
#define ITERATIONS 1000000000
32

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

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

    
47
LENGTH MainLoopGlobal(LENGTH iterations,unsigned int seed_w,unsigned int seed_z)
48
{
49
   unsigned int z=seed_z;
50
   unsigned int w=seed_w;
51

    
52
   LENGTH total=0;
53

    
54
   for (LENGTH i=0;i<iterations;i++) {
55

    
56
      float x=MWCfp ;
57
      float y=MWCfp ;
58

    
59
      // Matching test
60
      int inside=((x*x+y*y) < 1.0f) ? 1:0;
61
      total+=inside;
62
   }
63

    
64
   return(total);
65

    
66
}
67

    
68
int main(int argc, char *argv[]) {
69

    
70
  unsigned int seed_z=362436069,seed_w=52128862;
71
  LENGTH iterations=ITERATIONS,inside[1024],insides,part_inside,part_iterations;
72
  int numtasks,rank,rc,tag=1,i;
73
  float pi;
74

    
75
  char hostname[128];
76

    
77
  gethostname(hostname, sizeof hostname);
78

    
79
#ifdef TIME
80
  struct timeval start,end;
81
  long int useconds;
82
#endif
83

    
84
  MPI_Status Stat;
85

    
86
  rc = MPI_Init(&argc,&argv);
87
  if (rc != MPI_SUCCESS) {
88
    printf ("Error starting MPI program. Terminating.\n");
89
    MPI_Abort(MPI_COMM_WORLD, rc);
90
  }
91

    
92
  MPI_Comm_size(MPI_COMM_WORLD,&numtasks);
93
  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
94

    
95
  if (rank==0) {
96
    
97
    if (argc > 1) {
98
      iterations=(LENGTH)atoll(argv[1]);
99
    }
100
    else {
101
      printf("\n\tPi : Estimate Pi with Monte Carlo exploration\n\n");
102
      printf("\t\t#1 : number of iterations (default 1 billion)\n\n");
103
    }
104
    
105
    printf ("Sizeof int = %lld bytes.\n", (long long)sizeof(int));
106
    printf ("Sizeof long = %lld bytes.\n", (long long)sizeof(long));
107
    printf ("Sizeof long long = %lld bytes.\n", (long long)sizeof(long long));
108
    
109
    printf ("Max int = %u\n", INT_MAX);
110
    printf ("Max long = %ld\n", LONG_MAX);
111
    printf ("Max long long = %lld\n", LLONG_MAX);
112
    
113
    part_iterations=iterations/numtasks+1;
114
    
115
    // Split part of code
116
    for (i=1;i<numtasks;i++) {
117
      
118
#ifdef LONG
119
      rc = MPI_Send(&part_iterations, 1, MPI_LONG_LONG, i, tag, 
120
                    MPI_COMM_WORLD);
121
#else
122
      rc = MPI_Send(&part_iterations, 1, MPI_INT, i, tag, 
123
                    MPI_COMM_WORLD);
124
#endif
125
    }
126
    
127
#ifdef TIME
128
    gettimeofday(&start,(struct timezone *)0);
129
#endif
130
    
131
    insides=MainLoopGlobal(part_iterations,seed_w,seed_z);
132
    
133
#ifdef TIME
134
    gettimeofday(&end,(struct timezone *)0);
135
    useconds=(end.tv_sec-start.tv_sec)*1000000+end.tv_usec-start.tv_usec;
136
    
137
      printf("\tOn %s with rank %i, find %lld inside in %lu useconds.\n",
138
             hostname,rank,(long long)insides,useconds);
139
#else
140
      printf("\tOn %s with rank %i, find %lld inside\n",hostname,rank,
141
             (long long)insides);
142
      
143
#endif
144
      
145
    // Join part of code
146
      for (i=1;i<numtasks;i++) {
147
#ifdef LONG
148
        rc = MPI_Recv(&inside[i], 1, MPI_LONG_LONG, i, tag, 
149
                      MPI_COMM_WORLD, &Stat);
150
#else
151
        rc = MPI_Recv(&inside[i], 1, MPI_INT, i, tag, 
152
                      MPI_COMM_WORLD, &Stat);
153
#endif
154
        printf("\tReceive %lu inside from rank %i\n",(unsigned long)inside[i],i);
155
        insides+=inside[i];
156
      }
157
      
158
      pi=4.*(float)insides/(float)((iterations/numtasks)*numtasks);
159
      
160
      printf("\n\tPi=%.40f\n\twith error %.40f\n\twith %lld iterations\n\n",pi,
161
             fabs(pi-4*atan(1.))/pi,(long long)iterations);
162

    
163
  }
164
  else
165
    {
166
      // Receive information from master
167
#ifdef LONG
168
      rc = MPI_Recv(&part_iterations, 1, MPI_LONG_LONG, 0, tag, 
169
                    MPI_COMM_WORLD, &Stat);
170
#else
171
      rc = MPI_Recv(&part_iterations, 1, MPI_INT, 0, tag, 
172
                    MPI_COMM_WORLD, &Stat);
173
#endif
174
      
175
      printf("\tOn %s with rank %i, receive from master %lld\n",
176
             hostname,rank,(long long)part_iterations);
177
      
178
#ifdef TIME
179
      gettimeofday(&start,(struct timezone *)0);
180
#endif
181

    
182
      part_inside=MainLoopGlobal(part_iterations,rotr(seed_w,rank),rotl(seed_z,rank));
183
      
184
      
185
#ifdef TIME
186
      gettimeofday(&end,(struct timezone *)0);
187
      useconds=(end.tv_sec-start.tv_sec)*1000000+end.tv_usec-start.tv_usec;
188
      
189
      printf("\tOn %s with rank %i, find %lld inside in %lu useconds.\n",
190
             hostname,rank,(long long)part_inside,useconds);
191
#else
192
      printf("\tOn %s with rank %i, find %lld inside\n",hostname,rank,
193
             (long long)part_inside);
194
      
195
#endif
196
      
197
#ifdef LONG
198
      rc = MPI_Send(&part_inside, 1, MPI_LONG_LONG, 0, tag, MPI_COMM_WORLD);
199
#else
200
      rc = MPI_Send(&part_inside, 1, MPI_INT, 0, tag, MPI_COMM_WORLD);
201
#endif
202

    
203
    }
204
  
205
  MPI_Finalize();
206
  
207
}