Statistiques
| Révision :

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

Historique | Voir | Annoter | Télécharger (8,49 ko)

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