Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Length modifier 'l' is indeed wrong in %l[efg] for printf.
[simgrid.git] / examples / smpi / NAS / EP-trace / ep-trace.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <math.h>
5
6 #include "mpi.h"
7 #include "npbparams.h"
8
9 #include "instr/instr.h" //TRACE_
10
11 #include "randlc.h"
12
13 #ifndef CLASS
14 #define CLASS 'S'
15 #define NUM_PROCS            1                 
16 #endif
17 #define true 1
18 #define false 0
19
20
21 //---NOTE : all the timers function have been modified to
22 //          avoid global timers (privatize these). 
23       // ----------------------- timers ---------------------
24       void timer_clear(double *onetimer) {
25             //elapsed[n] = 0.0;
26             *onetimer = 0.0;
27       }
28
29       void timer_start(double *onetimer) {
30             *onetimer = MPI_Wtime();
31       }
32
33       void timer_stop(int n,double *elapsed,double *start) {
34             double t, now;
35
36             now = MPI_Wtime();
37             t = now - start[n];
38             elapsed[n] += t;
39       }
40
41       double timer_read(int n, double *elapsed) {  /* ok, useless, but jsut to keep function call */
42             return(elapsed[n]);
43       }
44       /********************************************************************
45        *****************            V R A N L C          ******************
46        *****************                                 *****************/           
47       double vranlc(int n, double x, double a, double *y)
48       {
49         int i;
50         long  i246m1=0x00003FFFFFFFFFFF;
51     long  LLx, Lx, La;
52         double d2m46;
53
54 // This doesn't work, because the compiler does the calculation in 32
55 // bits and overflows. No standard way (without f90 stuff) to specify
56 // that the rhs should be done in 64 bit arithmetic.
57 //     parameter(i246m1=2**46-1)
58
59       d2m46=pow(0.5,46);
60
61 // c Note that the v6 compiler on an R8000 does something stupid with
62 // c the above. Using the following instead (or various other things)
63 // c makes the calculation run almost 10 times as fast.
64 //
65 // c     save d2m46
66 // c      data d2m46/0.0d0/
67 // c      if (d2m46 .eq. 0.0d0) then
68 // c         d2m46 = 0.5d0**46
69 // c      endif
70
71       Lx = (long)x;
72       La = (long)a;
73       //fprintf(stdout,("================== Vranlc ================");
74       //fprintf(stdout,("Before Loop: Lx = " + Lx + ", La = " + La);
75   LLx = Lx;
76   for (i=0; i< n; i++) {
77       Lx   = Lx*La & i246m1 ;
78       LLx = Lx;
79       y[i] = d2m46 * (double)LLx;
80       /*
81          if(i == 0) {
82          fprintf(stdout,("After loop 0:");
83          fprintf(stdout,("Lx = " + Lx + ", La = " + La);
84          fprintf(stdout,("d2m46 = " + d2m46);
85          fprintf(stdout,("LLX(Lx) = " + LLX.doubleValue());
86          fprintf(stdout,("Y[0]" + y[0]);
87          }
88        */
89   }
90
91       x = (double)LLx;
92       /*
93       fprintf(stdout,("Change: Lx = " + Lx);
94       fprintf(stdout,("=============End   Vranlc ================");
95       */
96       return x;
97     }
98
99
100
101 //-------------- the core (unique function) -----------
102       void doTest(int argc, char **argv) {
103       double dum[3] = {1.,1.,1.};
104       double x1, x2, sx, sy, tm, an, tt, gc;
105       double Mops;
106       double epsilon=1.0E-8, a = 1220703125., s=271828183.;
107       double t1, t2, t3, t4; 
108       double sx_verify_value, sy_verify_value, sx_err, sy_err;
109
110 #include "npbparams.h"
111       int    mk=16, 
112          // --> set by make : in npbparams.h
113          //m=28, // for CLASS=A
114          //m=30, // for CLASS=B
115          //npm=2, // NPROCS
116          mm = m-mk, 
117          nn = (int)(pow(2,mm)), 
118          nk = (int)(pow(2,mk)), 
119          nq=10, 
120          np, 
121          node, 
122          no_nodes, 
123          i, 
124          ik, 
125          kk, 
126          l, 
127          k, nit, no_large_nodes,
128          np_add, k_offset, j;
129       int    me, nprocs, root=0, dp_type;
130       int verified, 
131           timers_enabled=true;
132       char  size[500]; // mind the size of the string to represent a big number
133
134       //Use in randlc..
135       int KS = 0;
136       double R23, R46, T23, T46;
137
138       double *qq = (double *) malloc (10000*sizeof(double));
139       double *start = (double *) malloc (64*sizeof(double));
140       double *elapsed = (double *) malloc (64*sizeof(double));
141
142       double *x = (double *) malloc (2*nk*sizeof(double));
143       double *q = (double *) malloc (nq*sizeof(double));
144
145       TRACE_smpi_set_category ("start");
146
147       MPI_Init( &argc, &argv );
148       MPI_Comm_size( MPI_COMM_WORLD, &no_nodes);
149       MPI_Comm_rank( MPI_COMM_WORLD, &node);
150
151 #ifdef USE_MPE
152     MPE_Init_log();
153 #endif
154       root = 0;
155       if (node == root ) {
156
157           /*   Because the size of the problem is too large to store in a 32-bit
158            *   integer for some classes, we put it into a string (for printing).
159            *   Have to strip off the decimal point put in there by the floating
160            *   point print statement (internal file)
161            */
162           fprintf(stdout," NAS Parallel Benchmarks 3.2 -- EP Benchmark");
163           sprintf(size,"%d",pow(2,m+1));
164           //size = size.replace('.', ' ');
165           fprintf(stdout," Number of random numbers generated: %s\n",size);
166           fprintf(stdout," Number of active processes: %d\n",no_nodes);
167
168       }
169       verified = false;
170
171       /* c   Compute the number of "batches" of random number pairs generated 
172          c   per processor. Adjust if the number of processors does not evenly 
173          c   divide the total number
174 */
175
176        np = nn / no_nodes;
177        no_large_nodes = nn % no_nodes;
178        if (node < no_large_nodes) np_add = 1;
179        else np_add = 0;
180        np = np + np_add;
181
182        if (np == 0) {
183              fprintf(stdout,"Too many nodes: %d  %d",no_nodes,nn);
184              MPI_Abort(MPI_COMM_WORLD,1);
185              exit(0); 
186        } 
187
188 /* c   Call the random number generator functions and initialize
189    c   the x-array to reduce the effects of paging on the timings.
190    c   Also, call all mathematical functions that are used. Make
191    c   sure these initializations cannot be eliminated as dead code.
192 */
193
194    //call vranlc(0, dum[1], dum[2], dum[3]);
195    // Array indexes start at 1 in Fortran, 0 in Java
196    vranlc(0, dum[0], dum[1], &(dum[2])); 
197
198    dum[0] = randlc(&(dum[1]),&(dum[2]));
199    /////////////////////////////////
200    for (i=0;i<2*nk;i++) {
201        x[i] = -1e99;
202    }
203    Mops = log(sqrt(abs(1))); 
204
205    /*
206       c---------------------------------------------------------------------
207       c    Synchronize before placing time stamp
208       c---------------------------------------------------------------------
209     */
210         MPI_Barrier( MPI_COMM_WORLD );
211
212
213       TRACE_smpi_set_category ("ep");
214
215         timer_clear(&(elapsed[1]));
216         timer_clear(&(elapsed[2]));
217         timer_clear(&(elapsed[3]));
218         timer_start(&(start[1]));
219         
220         t1 = a;
221   //fprintf(stdout,("(ep.f:160) t1 = " + t1);
222         t1 = vranlc(0, t1, a, x);
223   //fprintf(stdout,("(ep.f:161) t1 = " + t1);
224   
225         
226 /* c   Compute AN = A ^ (2 * NK) (mod 2^46). */
227         
228         t1 = a;
229   //fprintf(stdout,("(ep.f:165) t1 = " + t1);
230         for (i=1; i <= mk+1; i++) {
231                t2 = randlc(&t1, &t1);
232          //fprintf(stdout,("(ep.f:168)[loop i=" + i +"] t1 = " + t1);
233         } 
234         an = t1;
235   //fprintf(stdout,("(ep.f:172) s = " + s);
236         tt = s;
237         gc = 0.;
238         sx = 0.;
239         sy = 0.;
240         for (i=0; i < nq ; i++) {
241                q[i] = 0.;
242         }
243
244 /*
245     Each instance of this loop may be performed independently. We compute
246     the k offsets separately to take into account the fact that some nodes
247     have more numbers to generate than others
248 */
249
250       if (np_add == 1)
251          k_offset = node * np -1;
252       else
253          k_offset = no_large_nodes*(np+1) + (node-no_large_nodes)*np -1;
254      
255       int stop = false;
256       for(k = 1; k <= np; k++) {
257          stop = false;
258          kk = k_offset + k ;
259          t1 = s;
260          //fprintf(stdout,("(ep.f:193) t1 = " + t1);
261          t2 = an;
262
263 //       Find starting seed t1 for this kk.
264
265          for (i=1;i<=100 && !stop;i++) {
266             ik = kk / 2;
267       //fprintf(stdout,("(ep.f:199) ik = " +ik+", kk = " + kk);
268             if (2 * ik != kk)  {
269                 t3 = randlc(&t1, &t2);
270                 //fprintf(stdout,("(ep.f:200) t1= " +t1 );
271             }
272             if (ik==0)
273                 stop = true;
274             else {
275                t3 = randlc(&t2, &t2);
276                kk = ik;
277            }
278          }
279 //       Compute uniform pseudorandom numbers.
280
281          //if (timers_enabled)  timer_start(3);
282    timer_start(&(start[3]));
283          //call vranlc(2 * nk, t1, a, x)  --> t1 and y are modified
284
285   //fprintf(stdout,">>>>>>>>>>>Before vranlc(l.210)<<<<<<<<<<<<<");
286   //fprintf(stdout,"2*nk = " + (2*nk));
287   //fprintf(stdout,"t1 = " + t1);
288   //fprintf(stdout,"a  = " + a);
289   //fprintf(stdout,"x[0] = " + x[0]);
290   //fprintf(stdout,">>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<");
291         
292   t1 = vranlc(2 * nk, t1, a, x);
293
294   //fprintf(stdout,(">>>>>>>>>>>After  Enter vranlc (l.210)<<<<<<");
295   //fprintf(stdout,("2*nk = " + (2*nk));
296   //fprintf(stdout,("t1 = " + t1);
297   //fprintf(stdout,("a  = " + a);
298   //fprintf(stdout,("x[0] = " + x[0]);
299   //fprintf(stdout,(">>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<");
300         
301          //if (timers_enabled)  timer_stop(3);
302    timer_stop(3,elapsed,start);
303
304 /*       Compute Gaussian deviates by acceptance-rejection method and 
305  *       tally counts in concentric square annuli.  This loop is not 
306  *       vectorizable. 
307  */
308          //if (timers_enabled) timer_start(2);
309     timer_start(&(start[2]));
310          for(i=1; i<=nk;i++) {
311             x1 = 2. * x[2*i-2] -1.0;
312             x2 = 2. * x[2*i-1] - 1.0;
313             t1 = x1*x1 + x2*x2;
314             if (t1 <= 1.) {
315                t2   = sqrt(-2. * log(t1) / t1);
316                t3   = (x1 * t2);
317                t4   = (x2 * t2);
318                l    = (int)(abs(t3) > abs(t4) ? abs(t3) : abs(t4));
319                q[l] = q[l] + 1.;
320                sx   = sx + t3;
321                sy   = sy + t4;
322              }
323     /*
324        if(i == 1) {
325                 fprintf(stdout,"x1 = " + x1);
326                 fprintf(stdout,"x2 = " + x2);
327                 fprintf(stdout,"t1 = " + t1);
328                 fprintf(stdout,"t2 = " + t2);
329                 fprintf(stdout,"t3 = " + t3);
330                 fprintf(stdout,"t4 = " + t4);
331                 fprintf(stdout,"l = " + l);
332                 fprintf(stdout,"q[l] = " + q[l]);
333                 fprintf(stdout,"sx = " + sx);
334                 fprintf(stdout,"sy = " + sy);
335        }
336     */
337            }
338          //if (timers_enabled)  timer_stop(2);
339     timer_stop(2,elapsed,start);
340       }
341
342       TRACE_smpi_set_category ("finalize");
343
344       //int MPI_Allreduce(void *sbuf, void *rbuf, int count, MPI_Datatype dtype, MPI_Op op, MPI_Comm comm)   
345   MPI_Allreduce(&sx, x, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
346   sx = x[0]; //FIXME :  x[0] or x[1] => x[0] because fortran starts with 1
347       MPI_Allreduce(&sy, x, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
348       sy = x[0];
349       MPI_Allreduce(q, x, nq, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
350
351       for(i = 0; i < nq; i++) {
352     q[i] = x[i];
353   }
354   for(i = 0; i < nq; i++) {
355     gc += q[i];
356   }
357
358   timer_stop(1,elapsed,start);
359       tm = timer_read(1,elapsed);
360   MPI_Allreduce(&tm, x, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
361   tm = x[0];
362
363   if(node == root) {
364     nit = 0;
365     verified = true;
366
367     if(m == 24) {
368              sx_verify_value = -3.247834652034740E3;
369                   sy_verify_value = -6.958407078382297E3;
370     } else if(m == 25) {
371                 sx_verify_value = -2.863319731645753E3;
372       sy_verify_value = -6.320053679109499E3;
373     } else if(m == 28) {
374             sx_verify_value = -4.295875165629892E3;
375       sy_verify_value = -1.580732573678431E4;
376     } else if(m == 30) {
377             sx_verify_value =  4.033815542441498E4;
378                   sy_verify_value = -2.660669192809235E4;
379     } else if(m == 32) {
380                   sx_verify_value =  4.764367927995374E4;
381                      sy_verify_value = -8.084072988043731E4;
382     } else if(m == 36) {
383             sx_verify_value =  1.982481200946593E5;
384             sy_verify_value = -1.020596636361769E5;
385     } else {
386       verified = false;
387     }
388
389     /*
390     fprintf(stdout,("sx        = " + sx);
391     fprintf(stdout,("sx_verify = " + sx_verify_value);
392     fprintf(stdout,("sy        = " + sy);
393     fprintf(stdout,("sy_verify = " + sy_verify_value);
394     */
395     if(verified) {
396       sx_err = abs((sx - sx_verify_value)/sx_verify_value);
397       sy_err = abs((sy - sy_verify_value)/sy_verify_value);
398       /*
399       fprintf(stdout,("sx_err = " + sx_err);
400       fprintf(stdout,("sy_err = " + sx_err);
401       fprintf(stdout,("epsilon= " + epsilon);
402       */
403       verified = ((sx_err < epsilon) && (sy_err < epsilon));
404     }
405
406     Mops = (pow(2.0, m+1))/tm/1000;
407
408     fprintf(stdout,"EP Benchmark Results:\n");
409     fprintf(stdout,"CPU Time=%d\n",tm);
410     fprintf(stdout,"N = 2^%d\n",m);
411     fprintf(stdout,"No. Gaussain Pairs =%d\n",gc);
412     fprintf(stdout,"Sum = %f %ld\n",sx,sy);
413     fprintf(stdout,"Count:");
414     for(i = 0; i < nq; i++) {
415       fprintf(stdout,"%d\t %ld\n",i,q[i]);
416     }
417
418     /*
419     print_results("EP", _class, m+1, 0, 0, nit, npm, no_nodes, tm, Mops,
420         "Random numbers generated", verified, npbversion,
421         compiletime, cs1, cs2, cs3, cs4, cs5, cs6, cs7) */
422     fprintf(stdout,"\nEP Benchmark Completed\n");
423             fprintf(stdout,"Class           = %s\n", _class);
424     fprintf(stdout,"Size            = %s\n", size);
425     fprintf(stdout,"Iteration       = %d\n", nit);
426     fprintf(stdout,"Time in seconds = %f\n",(tm/1000));
427     fprintf(stdout,"Total processes = %d\n",no_nodes);
428     fprintf(stdout,"Mops/s total    = %f\n",Mops);
429     fprintf(stdout,"Mops/s/process  = %f\n", Mops/no_nodes);
430     fprintf(stdout,"Operation type  = Random number generated\n");
431     if(verified) {
432       fprintf(stdout,"Verification    = SUCCESSFUL\n");
433     } else {
434       fprintf(stdout,"Verification    = UNSUCCESSFUL\n");
435     }
436              fprintf(stdout,"Total time:     %f\n",(timer_read(1,elapsed)/1000));
437              fprintf(stdout,"Gaussian pairs: %f\n",(timer_read(2,elapsed)/1000));
438              fprintf(stdout,"Random numbers: %f\n",(timer_read(3,elapsed)/1000));
439          }
440 #ifdef USE_MPE
441     MPE_Finish_log(argv[0]);
442 #endif
443  
444        MPI_Finalize();
445       }
446
447     int main(int argc, char **argv) {
448        doTest(argc,argv);
449     }