Statistiques
| Révision :

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

Historique | Voir | Annoter | Télécharger (5,21 ko)

1 9 equemene
//
2 9 equemene
// Estimation of Pi using Monte Carlo exploration process
3 9 equemene
// gcc -std=c99 -O3 -o Pi Pi.c -lm
4 59 equemene
// Emmanuel Quemener <emmanuel.quemener@ens-lyon.fr>
5 9 equemene
6 56 equemene
// Needed for gethostname
7 56 equemene
#define _BSD_SOURCE
8 56 equemene
#include <sys/unistd.h>
9 56 equemene
10 9 equemene
#include <math.h>
11 9 equemene
#include <stdio.h>
12 9 equemene
#include <stdlib.h>
13 25 equemene
#include <limits.h>
14 9 equemene
#include <mpi.h>
15 9 equemene
16 23 equemene
#ifdef TIME
17 23 equemene
#include <sys/time.h>
18 23 equemene
#endif
19 23 equemene
20 9 equemene
// Marsaglia RNG very simple implementation
21 9 equemene
#define znew  ((z=36969*(z&65535)+(z>>16))<<16)
22 9 equemene
#define wnew  ((w=18000*(w&65535)+(w>>16))&65535)
23 9 equemene
#define MWC   (znew+wnew)
24 9 equemene
#define SHR3  (jsr=(jsr=(jsr=jsr^(jsr<<17))^(jsr>>13))^(jsr<<5))
25 9 equemene
#define CONG  (jcong=69069*jcong+1234567)
26 9 equemene
#define KISS  ((MWC^CONG)+SHR3)
27 9 equemene
28 9 equemene
#define MWCfp MWC * 2.328306435454494e-10f
29 9 equemene
#define KISSfp KISS * 2.328306435454494e-10f
30 9 equemene
31 9 equemene
#define ITERATIONS 1000000000
32 9 equemene
33 9 equemene
#ifdef LONG
34 25 equemene
#define LENGTH long long
35 9 equemene
#else
36 25 equemene
#define LENGTH int
37 9 equemene
#endif
38 9 equemene
39 56 equemene
unsigned int rotl(unsigned int value, int shift) {
40 56 equemene
    return (value << shift) | (value >> (sizeof(value) * CHAR_BIT - shift));
41 56 equemene
}
42 56 equemene
43 56 equemene
unsigned int rotr(unsigned int value, int shift) {
44 56 equemene
    return (value >> shift) | (value << (sizeof(value) * CHAR_BIT - shift));
45 56 equemene
}
46 56 equemene
47 9 equemene
LENGTH MainLoopGlobal(LENGTH iterations,unsigned int seed_w,unsigned int seed_z)
48 9 equemene
{
49 9 equemene
   unsigned int z=seed_z;
50 9 equemene
   unsigned int w=seed_w;
51 9 equemene
52 32 equemene
   LENGTH total=0;
53 9 equemene
54 9 equemene
   for (LENGTH i=0;i<iterations;i++) {
55 9 equemene
56 9 equemene
      float x=MWCfp ;
57 9 equemene
      float y=MWCfp ;
58 9 equemene
59 9 equemene
      // Matching test
60 9 equemene
      int inside=((x*x+y*y) < 1.0f) ? 1:0;
61 9 equemene
      total+=inside;
62 9 equemene
   }
63 9 equemene
64 9 equemene
   return(total);
65 9 equemene
66 9 equemene
}
67 9 equemene
68 9 equemene
int main(int argc, char *argv[]) {
69 9 equemene
70 56 equemene
  unsigned int seed_z=362436069,seed_w=52128862;
71 9 equemene
  LENGTH iterations=ITERATIONS,inside[1024],insides,part_inside,part_iterations;
72 9 equemene
  int numtasks,rank,rc,tag=1,i;
73 9 equemene
  float pi;
74 9 equemene
75 56 equemene
  char hostname[128];
76 56 equemene
77 56 equemene
  gethostname(hostname, sizeof hostname);
78 56 equemene
79 23 equemene
#ifdef TIME
80 23 equemene
  struct timeval start,end;
81 23 equemene
  long int useconds;
82 23 equemene
#endif
83 23 equemene
84 9 equemene
  MPI_Status Stat;
85 80 equemene
86 9 equemene
  rc = MPI_Init(&argc,&argv);
87 9 equemene
  if (rc != MPI_SUCCESS) {
88 9 equemene
    printf ("Error starting MPI program. Terminating.\n");
89 9 equemene
    MPI_Abort(MPI_COMM_WORLD, rc);
90 9 equemene
  }
91 9 equemene
92 9 equemene
  MPI_Comm_size(MPI_COMM_WORLD,&numtasks);
93 9 equemene
  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
94 9 equemene
95 9 equemene
  if (rank==0) {
96 56 equemene
97 9 equemene
    if (argc > 1) {
98 25 equemene
      iterations=(LENGTH)atoll(argv[1]);
99 9 equemene
    }
100 9 equemene
    else {
101 9 equemene
      printf("\n\tPi : Estimate Pi with Monte Carlo exploration\n\n");
102 9 equemene
      printf("\t\t#1 : number of iterations (default 1 billion)\n\n");
103 9 equemene
    }
104 56 equemene
105 42 equemene
    printf ("Sizeof int = %lld bytes.\n", (long long)sizeof(int));
106 42 equemene
    printf ("Sizeof long = %lld bytes.\n", (long long)sizeof(long));
107 42 equemene
    printf ("Sizeof long long = %lld bytes.\n", (long long)sizeof(long long));
108 56 equemene
109 25 equemene
    printf ("Max int = %u\n", INT_MAX);
110 25 equemene
    printf ("Max long = %ld\n", LONG_MAX);
111 25 equemene
    printf ("Max long long = %lld\n", LLONG_MAX);
112 56 equemene
113 23 equemene
    part_iterations=iterations/numtasks+1;
114 56 equemene
115 9 equemene
    // Split part of code
116 9 equemene
    for (i=1;i<numtasks;i++) {
117 56 equemene
118 25 equemene
#ifdef LONG
119 80 equemene
      rc = MPI_Send(&part_iterations, 1, MPI_LONG_LONG, i, tag,
120 80 equemene
                    MPI_COMM_WORLD);
121 25 equemene
#else
122 80 equemene
      rc = MPI_Send(&part_iterations, 1, MPI_INT, i, tag,
123 80 equemene
                    MPI_COMM_WORLD);
124 80 equemene
#endif
125 9 equemene
    }
126 9 equemene
127 23 equemene
#ifdef TIME
128 23 equemene
    gettimeofday(&start,(struct timezone *)0);
129 23 equemene
#endif
130 56 equemene
131 9 equemene
    insides=MainLoopGlobal(part_iterations,seed_w,seed_z);
132 56 equemene
133 23 equemene
#ifdef TIME
134 23 equemene
    gettimeofday(&end,(struct timezone *)0);
135 23 equemene
    useconds=(end.tv_sec-start.tv_sec)*1000000+end.tv_usec-start.tv_usec;
136 56 equemene
137 56 equemene
      printf("\tOn %s with rank %i, find %lld inside in %lu useconds.\n",
138 56 equemene
             hostname,rank,(long long)insides,useconds);
139 23 equemene
#else
140 56 equemene
      printf("\tOn %s with rank %i, find %lld inside\n",hostname,rank,
141 25 equemene
             (long long)insides);
142 56 equemene
143 23 equemene
#endif
144 56 equemene
145 9 equemene
    // Join part of code
146 56 equemene
      for (i=1;i<numtasks;i++) {
147 25 equemene
#ifdef LONG
148 80 equemene
        rc = MPI_Recv(&inside[i], 1, MPI_LONG_LONG, i, tag,
149 80 equemene
                      MPI_COMM_WORLD, &Stat);
150 25 equemene
#else
151 80 equemene
        rc = MPI_Recv(&inside[i], 1, MPI_INT, i, tag,
152 80 equemene
                      MPI_COMM_WORLD, &Stat);
153 25 equemene
#endif
154 56 equemene
        printf("\tReceive %lu inside from rank %i\n",(unsigned long)inside[i],i);
155 56 equemene
        insides+=inside[i];
156 56 equemene
      }
157 56 equemene
158 56 equemene
      pi=4.*(float)insides/(float)((iterations/numtasks)*numtasks);
159 56 equemene
160 56 equemene
      printf("\n\tPi=%.40f\n\twith error %.40f\n\twith %lld iterations\n\n",pi,
161 56 equemene
             fabs(pi-4*atan(1.))/pi,(long long)iterations);
162 56 equemene
163 9 equemene
  }
164 9 equemene
  else
165 9 equemene
    {
166 9 equemene
      // Receive information from master
167 25 equemene
#ifdef LONG
168 80 equemene
      rc = MPI_Recv(&part_iterations, 1, MPI_LONG_LONG, 0, tag,
169 80 equemene
                    MPI_COMM_WORLD, &Stat);
170 25 equemene
#else
171 80 equemene
      rc = MPI_Recv(&part_iterations, 1, MPI_INT, 0, tag,
172 80 equemene
                    MPI_COMM_WORLD, &Stat);
173 25 equemene
#endif
174 9 equemene
175 56 equemene
      printf("\tOn %s with rank %i, receive from master %lld\n",
176 56 equemene
             hostname,rank,(long long)part_iterations);
177 56 equemene
178 23 equemene
#ifdef TIME
179 23 equemene
      gettimeofday(&start,(struct timezone *)0);
180 23 equemene
#endif
181 23 equemene
182 56 equemene
      part_inside=MainLoopGlobal(part_iterations,rotr(seed_w,rank),rotl(seed_z,rank));
183 9 equemene
184 56 equemene
185 23 equemene
#ifdef TIME
186 56 equemene
      gettimeofday(&end,(struct timezone *)0);
187 56 equemene
      useconds=(end.tv_sec-start.tv_sec)*1000000+end.tv_usec-start.tv_usec;
188 56 equemene
189 56 equemene
      printf("\tOn %s with rank %i, find %lld inside in %lu useconds.\n",
190 56 equemene
             hostname,rank,(long long)part_inside,useconds);
191 23 equemene
#else
192 56 equemene
      printf("\tOn %s with rank %i, find %lld inside\n",hostname,rank,
193 25 equemene
             (long long)part_inside);
194 56 equemene
195 23 equemene
#endif
196 56 equemene
197 56 equemene
#ifdef LONG
198 80 equemene
      rc = MPI_Send(&part_inside, 1, MPI_LONG_LONG, 0, tag, MPI_COMM_WORLD);
199 56 equemene
#else
200 80 equemene
      rc = MPI_Send(&part_inside, 1, MPI_INT, 0, tag, MPI_COMM_WORLD);
201 56 equemene
#endif
202 23 equemene
203 9 equemene
    }
204 9 equemene
205 9 equemene
  MPI_Finalize();
206 56 equemene
207 9 equemene
}