Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
fixing codacy warnings on multi-core VM tests + using a dedicated platform file for...
[simgrid.git] / examples / smpi / NAS / ep.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <math.h>
5 #include "smpi/mpi.h"
6 #include "nas_common.h"
7 #include "simgrid/instr.h" //TRACE_
8
9 char class;
10 int nprocs;
11
12 #define TRUE 1
13 #define FALSE 0
14
15 int main(int argc, char **argv) {
16   double dum[3] = {1.,1.,1.};
17   double x1, x2, sx, sy, tm, an, gc;
18   XBT_ATTRIB_UNUSED double tt;
19   double Mops;
20   double epsilon=1.0E-8, a = 1220703125., s=271828183.;
21   double t1, t2, t3, t4;
22   double sx_verify_value, sy_verify_value, sx_err, sy_err;
23
24   int    m;
25   int    mk=16;
26   int    nk = (int)(pow(2,mk)),
27          nq=10, 
28          np, node, no_nodes, i, ik, kk, l, k, nit, no_large_nodes, np_add, k_offset;
29   int    verified;
30   char   size[500]; // mind the size of the string to represent a big number
31
32   double *x = (double *) SMPI_SHARED_MALLOC (2*nk*sizeof(double));
33   double *q = (double *) SMPI_SHARED_MALLOC (nq*sizeof(double));
34
35   MPI_Init( &argc, &argv );
36   MPI_Comm_size( MPI_COMM_WORLD, &no_nodes);
37   MPI_Comm_rank( MPI_COMM_WORLD, &node);
38
39   TRACE_smpi_set_category ("start");
40
41   get_info(argc, argv, &nprocs, &class);
42   check_info(EP, nprocs, class);
43
44   if      (class == 'S')
45     { m = 24; }
46   else if (class == 'W')
47     { m = 25; }
48   else if (class == 'A')
49     { m = 28; }
50   else if (class == 'B')
51     { m = 30; }
52   else if (class == 'C')
53     { m = 32; }
54   else if (class == 'D')
55     { m = 36; }
56   else if (class == 'E')
57     { m = 40; }
58   else {
59     printf("EP: Internal error: invalid class type %c\n", class);
60     exit(1);
61   }
62
63   int mm = m -mk;
64   int nn = (int)(pow(2,mm));
65
66   int root = 0;
67   if (node == root ) {
68     /* Because the size of the problem is too large to store in a 32-bit integer for some classes, we put it into a
69      * string (for printing). Have to strip off the decimal point put in there by the floating point print statement
70      * (internal file) */
71     fprintf(stdout," NAS Parallel Benchmarks 3.2 -- EP Benchmark");
72     snprintf(size,500,"%lu",(unsigned long)pow(2,m+1));
73     fprintf(stdout," Number of random numbers generated: %s\n",size);
74     fprintf(stdout," Number of active processes: %d\n",no_nodes);
75   }
76   verified = FALSE;
77
78   /* Compute the number of "batches" of random number pairs generated per processor. Adjust if the number of processors
79    * does not evenly divide the total number  */
80   np = nn / no_nodes;
81   no_large_nodes = nn % no_nodes;
82   if (node < no_large_nodes)
83     np_add = 1;
84   else
85     np_add = 0;
86   np = np + np_add;
87
88   if (np == 0) {
89     fprintf(stdout,"Too many nodes: %d  %d",no_nodes,nn);
90     MPI_Abort(MPI_COMM_WORLD,1);
91     exit(0);
92   }
93
94   /* Call the random number generator functions and initialize the x-array to reduce the effects of paging the timings.
95    Also, call all mathematical functions that are used. Make sure initializations cannot be eliminated as dead code. */
96   vranlc(0, dum[0], dum[1], &(dum[2]));
97
98   dum[0] = randlc(&(dum[1]),&(dum[2]));
99   for (i=0;i<2*nk;i++) {
100     x[i] = -1e99;
101   }
102   Mops = log(sqrt(abs(1)));
103
104   /* Synchronize before placing time stamp */
105   MPI_Barrier( MPI_COMM_WORLD );
106
107   TRACE_smpi_set_category ("ep");
108
109   timer_clear(1);
110   timer_clear(2);
111   timer_clear(3);
112   timer_start(1);
113
114   t1 = a;
115   t1 = vranlc(0, t1, a, x);
116
117   /* Compute AN = A ^ (2 * NK) (mod 2^46). */
118   t1 = a;
119   for (i=1; i <= mk+1; i++) {
120     t2 = randlc(&t1, &t1);
121   }
122   an = t1;
123   tt = s;
124   gc = 0;
125   tt = 0.;
126   sx = 0.;
127   sy = 0.;
128   for (i=0; i < nq ; i++) {
129     q[i] = 0.;
130   }
131
132 /* Each instance of this loop may be performed independently. We compute the k offsets separately to take into account
133  * the fact that some nodes have more numbers to generate than others */
134   if (np_add == 1)
135     k_offset = node * np -1;
136   else
137     k_offset = no_large_nodes*(np+1) + (node-no_large_nodes)*np -1;
138
139   int stop = FALSE;
140   for(k = 1; k <= np; k++) { SMPI_SAMPLE_GLOBAL(0.25 * np, 0.03) {
141     stop = FALSE;
142     kk = k_offset + k ;
143     t1 = s;
144     t2 = an;
145
146     //       Find starting seed t1 for this kk.
147     for (i=1;i<=100 && !stop;i++) {
148       ik = kk / 2;
149       if (2 * ik != kk)  {
150         t3 = randlc(&t1, &t2);
151       }
152       if (ik==0)
153         stop = TRUE;
154       else {
155         t3 = randlc(&t2, &t2);
156         kk = ik;
157       }
158     }
159     //       Compute uniform pseudorandom numbers.
160
161     timer_start(3);
162
163     t1 = vranlc(2 * nk, t1, a, x);
164
165     timer_stop(3);
166
167     /* Compute Gaussian deviates by acceptance-rejection method and tally counts in concentric square annuli.
168      * This loop is not vectorizable. */
169     timer_start(2);
170
171     for(i=1; i<=nk;i++) {
172       x1 = 2. * x[2*i-2] -1.0;
173       x2 = 2. * x[2*i-1] - 1.0;
174       t1 = x1*x1 + x2*x2;
175       if (t1 <= 1.) {
176         t2   = sqrt(-2. * log(t1) / t1);
177         t3   = (x1 * t2);
178         t4   = (x2 * t2);
179         l    = (int)(fabs(t3) > fabs(t4) ? fabs(t3) : fabs(t4));
180         q[l] = q[l] + 1.;
181         sx   = sx + t3;
182         sy   = sy + t4;
183       }
184     }
185     timer_stop(2);
186     } }
187
188   TRACE_smpi_set_category ("finalize");
189
190   MPI_Allreduce(&sx, x, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
191   sx = x[0];
192   MPI_Allreduce(&sy, x, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
193   sy = x[0];
194   MPI_Allreduce(q, x, nq, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
195
196   for(i = 0; i < nq; i++) {
197     q[i] = x[i];
198   }
199   for(i = 0; i < nq; i++) {
200     gc += q[i];
201   }
202
203   timer_stop(1);
204   tm = timer_read(1);
205   MPI_Allreduce(&tm, x, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
206   tm = x[0];
207
208   SMPI_SHARED_FREE(x);
209
210   if(node == root) {
211     nit = 0;
212     verified = TRUE;
213
214     if(m == 24) {
215       sx_verify_value = -3.247834652034740E3;
216       sy_verify_value = -6.958407078382297E3;
217     } else if(m == 25) {
218       sx_verify_value = -2.863319731645753E3;
219       sy_verify_value = -6.320053679109499E3;
220     } else if(m == 28) {
221       sx_verify_value = -4.295875165629892E3;
222       sy_verify_value = -1.580732573678431E4;
223     } else if(m == 30) {
224       sx_verify_value =  4.033815542441498E4;
225       sy_verify_value = -2.660669192809235E4;
226     } else if(m == 32) {
227       sx_verify_value =  4.764367927995374E4;
228       sy_verify_value = -8.084072988043731E4;
229     } else if(m == 36) {
230       sx_verify_value =  1.982481200946593E5;
231       sy_verify_value = -1.020596636361769E5;
232     } else {
233       verified = FALSE;
234     }
235
236     if(verified) {
237       sx_err = fabs((sx - sx_verify_value)/sx_verify_value);
238       sy_err = fabs((sy - sy_verify_value)/sy_verify_value);
239       verified = ((sx_err < epsilon) && (sy_err < epsilon));
240     }
241
242     Mops = (pow(2.0, m+1))/tm/1000;
243
244     fprintf(stdout,"EP Benchmark Results:\n");
245     fprintf(stdout,"CPU Time=%d\n",(int) tm);
246     fprintf(stdout,"N = 2^%d\n",m);
247     fprintf(stdout,"No. Gaussain Pairs =%d\n",(int) gc);
248     fprintf(stdout,"Sum = %f %ld\n",sx,(long) sy);
249     fprintf(stdout,"Count:");
250     for(i = 0; i < nq; i++) {
251       fprintf(stdout,"%d\t %ld\n",i,(long) q[i]);
252     }
253     c_print_results("EP", class, m+1, 0, 0, nit, nprocs, no_nodes, tm, Mops, "Random number generated",verified);
254
255     fprintf(stdout,"Total time:     %f\n",(timer_read(1)/1000));
256     fprintf(stdout,"Gaussian pairs: %f\n",(timer_read(2)/1000));
257     fprintf(stdout,"Random numbers: %f\n",(timer_read(3)/1000));
258   }
259
260   SMPI_SHARED_FREE(q);
261
262   MPI_Finalize();
263   return 0;
264 }