Statistiques
| Révision :

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

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

1 80 equemene
//
2 80 equemene
// Estimation of Pi using Monte Carlo exploration process
3 126 equemene
// gcc -std=c99 -O3 -o Pi_aMPI Pi_aMPI.c -lm
4 80 equemene
// Emmanuel Quemener <emmanuel.quemener@ens-lyon.fr>
5 80 equemene
6 80 equemene
// Needed for gethostname
7 80 equemene
#define _BSD_SOURCE
8 80 equemene
#include <sys/unistd.h>
9 80 equemene
10 80 equemene
#include <math.h>
11 80 equemene
#include <stdio.h>
12 80 equemene
#include <stdlib.h>
13 80 equemene
#include <limits.h>
14 80 equemene
#include <mpi.h>
15 126 equemene
#include <stddef.h>
16 80 equemene
17 80 equemene
#include <sys/time.h>
18 80 equemene
19 80 equemene
// Marsaglia RNG very simple implementation
20 80 equemene
#define znew  ((z=36969*(z&65535)+(z>>16))<<16)
21 80 equemene
#define wnew  ((w=18000*(w&65535)+(w>>16))&65535)
22 80 equemene
#define MWC   (znew+wnew)
23 80 equemene
#define SHR3  (jsr=(jsr=(jsr=jsr^(jsr<<17))^(jsr>>13))^(jsr<<5))
24 80 equemene
#define CONG  (jcong=69069*jcong+1234567)
25 80 equemene
#define KISS  ((MWC^CONG)+SHR3)
26 80 equemene
27 80 equemene
#define MWCfp MWC * 2.328306435454494e-10f
28 80 equemene
#define KISSfp KISS * 2.328306435454494e-10f
29 80 equemene
#define SHR3fp SHR3 * 2.328306435454494e-10f
30 80 equemene
#define CONGfp CONG * 2.328306435454494e-10f
31 80 equemene
32 80 equemene
#define ITERATIONS 1000000000
33 80 equemene
34 80 equemene
#ifdef LONG
35 80 equemene
#define LENGTH long long
36 80 equemene
#else
37 80 equemene
#define LENGTH int
38 80 equemene
#endif
39 80 equemene
40 126 equemene
typedef struct compute_node {
41 126 equemene
        LENGTH inside;
42 126 equemene
        long int useconds;
43 126 equemene
} result;
44 126 equemene
45 80 equemene
unsigned int rotl(unsigned int value, int shift) {
46 80 equemene
    return (value << shift) | (value >> (sizeof(value) * CHAR_BIT - shift));
47 80 equemene
}
48 80 equemene
49 80 equemene
unsigned int rotr(unsigned int value, int shift) {
50 80 equemene
    return (value >> shift) | (value << (sizeof(value) * CHAR_BIT - shift));
51 80 equemene
}
52 80 equemene
53 80 equemene
LENGTH MainLoopGlobal(LENGTH iterations,unsigned int seed_w,unsigned int seed_z)
54 80 equemene
{
55 80 equemene
#if defined TCONG
56 80 equemene
   unsigned int jcong=seed_z;
57 80 equemene
#elif defined TSHR3
58 80 equemene
   unsigned int jsr=seed_w;
59 80 equemene
#elif defined TMWC
60 80 equemene
   unsigned int z=seed_z;
61 80 equemene
   unsigned int w=seed_w;
62 80 equemene
#elif defined TKISS
63 80 equemene
   unsigned int jcong=seed_z;
64 80 equemene
   unsigned int jsr=seed_w;
65 80 equemene
   unsigned int z=seed_z;
66 80 equemene
   unsigned int w=seed_w;
67 80 equemene
#endif
68 80 equemene
69 80 equemene
  LENGTH total=0;
70 80 equemene
71 80 equemene
   for (LENGTH i=0;i<iterations;i++) {
72 80 equemene
73 80 equemene
#if defined TINT32
74 80 equemene
    #define THEONE 1073741824
75 80 equemene
    #if defined TCONG
76 80 equemene
        unsigned int x=CONG>>17 ;
77 80 equemene
        unsigned int y=CONG>>17 ;
78 80 equemene
    #elif defined TSHR3
79 80 equemene
        unsigned int x=SHR3>>17 ;
80 80 equemene
        unsigned int y=SHR3>>17 ;
81 80 equemene
    #elif defined TMWC
82 80 equemene
        unsigned int x=MWC>>17 ;
83 80 equemene
        unsigned int y=MWC>>17 ;
84 80 equemene
    #elif defined TKISS
85 80 equemene
        unsigned int x=KISS>>17 ;
86 80 equemene
        unsigned int y=KISS>>17 ;
87 80 equemene
    #endif
88 80 equemene
#elif defined TINT64
89 80 equemene
    #define THEONE 4611686018427387904
90 80 equemene
    #if defined TCONG
91 80 equemene
        unsigned long x=(unsigned long)(CONG>>1) ;
92 80 equemene
        unsigned long y=(unsigned long)(CONG>>1) ;
93 80 equemene
    #elif defined TSHR3
94 80 equemene
        unsigned long x=(unsigned long)(SHR3>>1) ;
95 80 equemene
        unsigned long y=(unsigned long)(SHR3>>1) ;
96 80 equemene
    #elif defined TMWC
97 80 equemene
        unsigned long x=(unsigned long)(MWC>>1) ;
98 80 equemene
        unsigned long y=(unsigned long)(MWC>>1) ;
99 80 equemene
    #elif defined TKISS
100 80 equemene
        unsigned long x=(unsigned long)(KISS>>1) ;
101 80 equemene
        unsigned long y=(unsigned long)(KISS>>1) ;
102 80 equemene
    #endif
103 80 equemene
#elif defined TFP32
104 80 equemene
    #define THEONE 1.0f
105 80 equemene
    #if defined TCONG
106 80 equemene
        float x=CONGfp ;
107 80 equemene
        float y=CONGfp ;
108 80 equemene
    #elif defined TSHR3
109 80 equemene
        float x=SHR3fp ;
110 80 equemene
        float y=SHR3fp ;
111 80 equemene
    #elif defined TMWC
112 80 equemene
        float x=MWCfp ;
113 80 equemene
        float y=MWCfp ;
114 80 equemene
    #elif defined TKISS
115 80 equemene
      float x=KISSfp ;
116 80 equemene
      float y=KISSfp ;
117 80 equemene
    #endif
118 80 equemene
#elif defined TFP64
119 80 equemene
    #define THEONE 1.0f
120 80 equemene
    #if defined TCONG
121 80 equemene
        double x=(double)CONGfp ;
122 80 equemene
        double y=(double)CONGfp ;
123 80 equemene
    #elif defined TSHR3
124 80 equemene
        double x=(double)SHR3fp ;
125 80 equemene
        double y=(double)SHR3fp ;
126 80 equemene
    #elif defined TMWC
127 80 equemene
        double x=(double)MWCfp ;
128 80 equemene
        double y=(double)MWCfp ;
129 80 equemene
    #elif defined TKISS
130 80 equemene
        double x=(double)KISSfp ;
131 80 equemene
        double y=(double)KISSfp ;
132 80 equemene
    #endif
133 80 equemene
#endif
134 80 equemene
135 80 equemene
      // Matching test
136 80 equemene
      unsigned long inside=((x*x+y*y) < THEONE) ? 1:0;
137 80 equemene
      total+=inside;
138 80 equemene
   }
139 80 equemene
140 80 equemene
   return(total);
141 80 equemene
142 80 equemene
}
143 80 equemene
144 80 equemene
int main(int argc, char *argv[]) {
145 80 equemene
146 80 equemene
  unsigned int seed_z=362436069,seed_w=52128862;
147 126 equemene
  LENGTH iterations=ITERATIONS,inside[8192],insides,part_inside,part_iterations;
148 80 equemene
  int numtasks,rank,rc,tag=1,i;
149 80 equemene
  float pi;
150 80 equemene
151 80 equemene
  char hostname[128];
152 80 equemene
153 80 equemene
  gethostname(hostname, sizeof hostname);
154 80 equemene
155 80 equemene
#ifdef TIME
156 80 equemene
  struct timeval start,end;
157 80 equemene
  long int useconds;
158 80 equemene
#endif
159 80 equemene
160 80 equemene
  MPI_Status Stat;
161 80 equemene
  MPI_Request RequestSend, RequestRecv, RequestSend2, RequestRecv2;
162 80 equemene
163 80 equemene
  rc = MPI_Init(&argc,&argv);
164 80 equemene
  if (rc != MPI_SUCCESS) {
165 80 equemene
    printf ("Error starting MPI program. Terminating.\n");
166 80 equemene
    MPI_Abort(MPI_COMM_WORLD, rc);
167 80 equemene
  }
168 80 equemene
169 80 equemene
  MPI_Comm_size(MPI_COMM_WORLD,&numtasks);
170 80 equemene
  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
171 126 equemene
172 126 equemene
  MPI_Comm_size(MPI_COMM_WORLD,&numtasks);
173 126 equemene
  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
174 80 equemene
175 126 equemene
  const int nitems=2;
176 126 equemene
  int blocklengths[2] = {1,1};
177 126 equemene
178 126 equemene
#ifdef LONG
179 126 equemene
  MPI_Datatype types[2] = {MPI_LONG, MPI_LONG};
180 126 equemene
#else
181 126 equemene
  MPI_Datatype types[2] = {MPI_INT, MPI_LONG};
182 126 equemene
#endif
183 126 equemene
184 126 equemene
  MPI_Datatype mpi_result_type;
185 126 equemene
  MPI_Aint     offsets[2];
186 126 equemene
187 126 equemene
  offsets[0] = offsetof(result, inside);
188 126 equemene
  offsets[1] = offsetof(result, useconds);
189 126 equemene
190 126 equemene
  MPI_Type_create_struct(nitems, blocklengths, offsets, types, &mpi_result_type);
191 126 equemene
  MPI_Type_commit(&mpi_result_type);
192 126 equemene
193 80 equemene
  if (rank==0) {
194 80 equemene
195 80 equemene
    if (argc > 1) {
196 80 equemene
      iterations=(LENGTH)atoll(argv[1]);
197 80 equemene
    }
198 80 equemene
    else {
199 80 equemene
      printf("\n\tPi : Estimate Pi with Monte Carlo exploration\n\n");
200 80 equemene
      printf("\t\t#1 : number of iterations (default 1 billion)\n\n");
201 80 equemene
    }
202 80 equemene
203 126 equemene
    printf ("\tSizeof int = %lld bytes.\n", (long long)sizeof(int));
204 126 equemene
    printf ("\tSizeof long = %lld bytes.\n", (long long)sizeof(long));
205 126 equemene
    printf ("\tSizeof long long = %lld bytes.\n", (long long)sizeof(long long));
206 80 equemene
207 126 equemene
    printf ("\tMax int = %u\n", INT_MAX);
208 126 equemene
    printf ("\tMax long = %ld\n", LONG_MAX);
209 126 equemene
    printf ("\tMax long long = %lld\n", LLONG_MAX);
210 80 equemene
211 126 equemene
    part_iterations=((iterations%numtasks) == 0) ? iterations/numtasks:iterations/numtasks+1 ;
212 80 equemene
213 80 equemene
    // Split part of code
214 80 equemene
    for (i=1;i<numtasks;i++) {
215 80 equemene
216 80 equemene
#ifdef LONG
217 80 equemene
      rc = MPI_Isend(&part_iterations, 1, MPI_LONG_LONG, i, tag,
218 80 equemene
                     MPI_COMM_WORLD,&RequestSend);
219 80 equemene
#else
220 80 equemene
      rc = MPI_Isend(&part_iterations, 1, MPI_INT, i, tag,
221 80 equemene
                     MPI_COMM_WORLD,&RequestSend);
222 80 equemene
#endif
223 80 equemene
    }
224 87 equemene
    if (numtasks>1) {
225 87 equemene
      MPI_Wait(&RequestSend, &Stat);
226 87 equemene
    }
227 80 equemene
228 80 equemene
    gettimeofday(&start,(struct timezone *)0);
229 80 equemene
230 80 equemene
    insides=MainLoopGlobal(part_iterations,seed_w,seed_z);
231 80 equemene
232 80 equemene
    gettimeofday(&end,(struct timezone *)0);
233 80 equemene
    useconds=(end.tv_sec-start.tv_sec)*1000000+end.tv_usec-start.tv_usec;
234 80 equemene
235 126 equemene
    printf("\tOn %s with rank %i, find %lld inside in %lu useconds.\n",
236 80 equemene
             hostname,rank,(long long)insides,useconds);
237 80 equemene
238 80 equemene
    // Join part of code
239 80 equemene
      for (i=1;i<numtasks;i++) {
240 126 equemene
241 126 equemene
        result recv;
242 126 equemene
243 126 equemene
        rc = MPI_Irecv(&recv, 1, mpi_result_type, i, tag,
244 80 equemene
                      MPI_COMM_WORLD, &RequestRecv2);
245 126 equemene
246 87 equemene
        if (numtasks>1) {
247 87 equemene
            MPI_Wait(&RequestRecv2, &Stat);
248 87 equemene
        }
249 80 equemene
250 126 equemene
        inside[i]=recv.inside;
251 126 equemene
        useconds=recv.useconds;
252 126 equemene
253 126 equemene
        printf("\tReceive from %i, find %lld inside in %lu useconds\n",i,(long long)inside[i],useconds);
254 126 equemene
255 80 equemene
        insides+=inside[i];
256 80 equemene
      }
257 80 equemene
258 126 equemene
      pi=4.*(float)insides/(float)(part_iterations*numtasks);
259 80 equemene
260 80 equemene
      printf("\n\tPi=%.40f\n\twith error %.40f\n\twith %lld iterations\n\n",pi,
261 80 equemene
             fabs(pi-4*atan(1.))/pi,(long long)iterations);
262 80 equemene
263 80 equemene
  }
264 80 equemene
  else
265 80 equemene
    {
266 80 equemene
      // Receive information from master
267 126 equemene
268 80 equemene
#ifdef LONG
269 80 equemene
      rc = MPI_Irecv(&part_iterations, 1, MPI_LONG_LONG, 0, tag,
270 80 equemene
                    MPI_COMM_WORLD, &RequestRecv);
271 80 equemene
#else
272 80 equemene
      rc = MPI_Irecv(&part_iterations, 1, MPI_INT, 0, tag,
273 80 equemene
                    MPI_COMM_WORLD, &RequestRecv);
274 80 equemene
#endif
275 80 equemene
      MPI_Wait(&RequestRecv, &Stat);
276 80 equemene
277 126 equemene
      /* Not such a good idea to print information...
278 126 equemene
         printf("\tOn %s with rank %i, receive from master %lld\n",
279 126 equemene
         hostname,rank,(long long)part_iterations); */
280 80 equemene
281 80 equemene
      gettimeofday(&start,(struct timezone *)0);
282 80 equemene
283 80 equemene
      part_inside=MainLoopGlobal(part_iterations,rotr(seed_w,rank),rotl(seed_z,rank));
284 80 equemene
285 80 equemene
      gettimeofday(&end,(struct timezone *)0);
286 80 equemene
      useconds=(end.tv_sec-start.tv_sec)*1000000+end.tv_usec-start.tv_usec;
287 126 equemene
288 126 equemene
      /*
289 80 equemene
      printf("\tOn %s with rank %i, find %lld inside in %lu useconds.\n",
290 80 equemene
             hostname,rank,(long long)part_inside,useconds);
291 126 equemene
      */
292 126 equemene
293 126 equemene
      result send;
294 126 equemene
      send.inside=part_inside;
295 126 equemene
      send.useconds=useconds;
296 80 equemene
297 126 equemene
      rc = MPI_Isend(&send, 1, mpi_result_type, 0, tag, MPI_COMM_WORLD,&RequestSend2);
298 126 equemene
299 80 equemene
      MPI_Wait(&RequestSend2, &Stat);
300 80 equemene
301 80 equemene
    }
302 126 equemene
303 126 equemene
  MPI_Type_free(&mpi_result_type);
304 80 equemene
  MPI_Finalize();
305 80 equemene
306 80 equemene
}