Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of scm.gforge.inria.fr:/gitroot/simgrid/simgrid
[simgrid.git] / examples / smpi / NAS / nas_common.c
1 /* Copyright (c) 2016. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6 #include "nas_common.h"
7
8 static double start[64], elapsed[64];
9
10 /* integer log base two. Return error is argument isn't a power of two or is less than or equal to zero */
11 int ilog2(int i)
12 {
13   int log2;
14   int exp2 = 1;
15   if (i <= 0) return(-1);
16
17   for (log2 = 0; log2 < 20; log2++) {
18     if (exp2 == i) return(log2);
19     exp2 *= 2;
20   }
21   return(-1);
22 }
23
24 /*  get_info(): Get parameters from command line */
25 void get_info(int argc, char *argv[], int *nprocsp, char *classp)
26 {
27   if (argc < 3) {
28     printf("Usage: %s (%d) nprocs class\n", argv[0], argc);
29     exit(1);
30   }
31
32   *nprocsp = atoi(argv[1]);
33   *classp = *argv[2];
34 }
35
36 /*  check_info(): Make sure command line data is ok for this benchmark */
37 void check_info(int type, int nprocs, char class)
38 {
39   int logprocs;
40
41   /* check number of processors */
42   if (nprocs <= 0) {
43     printf("setparams: Number of processors must be greater than zero\n");
44     exit(1);
45   }
46   switch(type) {
47   case IS:
48     logprocs = ilog2(nprocs);
49     if (logprocs < 0) {
50       printf("setparams: Number of processors must be a power of two (1,2,4,...) for this benchmark\n");
51       exit(1);
52     }
53     break;
54   case EP:
55   case DT:
56     break;
57   default:
58     /* never should have gotten this far with a bad name */
59     printf("setparams: (Internal Error) Benchmark type %d unknown to this program\n", type);
60     exit(1);
61   }
62
63   /* check class */
64   if (class != 'S' && class != 'W' && class != 'A' && class != 'B' && class != 'C' && class != 'D' && class != 'E') {
65     printf("setparams: Unknown benchmark class %c\n", class);
66     printf("setparams: Allowed classes are \"S\", \"W\", and \"A\" through \"E\"\n");
67     exit(1);
68   }
69
70   if (class == 'E' && (type == IS || type == DT)) {
71     printf("setparams: Benchmark class %c not defined for IS or DT\n", class);
72     exit(1);
73   }
74
75   if (class == 'D' && type == IS && nprocs < 4) {
76     printf("setparams: IS class D size cannot be run on less than 4 processors\n");
77     exit(1);
78   }
79 }
80
81 void time_clear(double *onetimer) {
82  *onetimer = 0.0;
83 }
84
85 void time_start(double *onetimer) {
86  *onetimer = MPI_Wtime();
87 }
88
89 void time_stop(int n,double *elapsed,double *start) {
90   elapsed[n] = MPI_Wtime()- start[n];
91 }
92
93 double time_read(int n, double *elapsed) {  /* ok, useless, but jsut to keep function call */
94   return(elapsed[n]);
95 }
96
97 void timer_clear(int n)
98 {
99   elapsed[n] = 0.0;
100 }
101
102 void timer_start(int n)
103 {
104   start[n] = MPI_Wtime();
105 }
106
107 void timer_stop(int n)
108 {
109   elapsed[n] += MPI_Wtime() - start[n];
110 }
111
112 double timer_read(int n)
113 {
114   return elapsed[n];
115 }
116
117 double vranlc(int n, double x, double a, double *y)
118 {
119   int i;
120   long  i246m1=0x00003FFFFFFFFFFF;
121   long  LLx, Lx, La;
122   double d2m46;
123
124 // This doesn't work, because the compiler does the calculation in 32 bits and overflows. No standard way (without
125 // f90 stuff) to specifythat the rhs should be done in 64 bit arithmetic.
126 // parameter(i246m1=2**46-1)
127
128   d2m46=pow(0.5,46);
129
130   Lx = (long)x;
131   La = (long)a;
132   //fprintf(stdout,("================== Vranlc ================");
133   //fprintf(stdout,("Before Loop: Lx = " + Lx + ", La = " + La);
134   LLx = Lx;
135   for (i=0; i< n; i++) {
136     Lx   = Lx*La & i246m1 ;
137     LLx = Lx;
138     y[i] = d2m46 * (double)LLx;
139     /*
140      if(i == 0) {
141        fprintf(stdout,("After loop 0:");
142        fprintf(stdout,("Lx = " + Lx + ", La = " + La);
143        fprintf(stdout,("d2m46 = " + d2m46);
144        fprintf(stdout,("LLX(Lx) = " + LLX.doubleValue());
145        fprintf(stdout,("Y[0]" + y[0]);
146      }
147      */
148   }
149
150   x = (double)LLx;
151   /*
152   fprintf(stdout,("Change: Lx = " + Lx);
153   fprintf(stdout,("=============End   Vranlc ================");
154    */
155   return x;
156 }
157
158 /*
159  *    FUNCTION RANDLC (X, A)
160  *
161  *  This routine returns a uniform pseudorandom double precision number in the
162  *  range (0, 1) by using the linear congruential generator
163  *
164  *  x_{k+1} = a x_k  (mod 2^46)
165  *
166  *  where 0 < x_k < 2^46 and 0 < a < 2^46.  This scheme generates 2^44 numbers
167  *  before repeating.  The argument A is the same as 'a' in the above formula,
168  *  and X is the same as x_0.  A and X must be odd double precision integers
169  *  in the range (1, 2^46).  The returned value RANDLC is normalized to be
170  *  between 0 and 1, i.e. RANDLC = 2^(-46) * x_1.  X is updated to contain
171  *  the new seed x_1, so that subsequent calls to RANDLC using the same
172  *  arguments will generate a continuous sequence.
173  *
174  *  This routine should produce the same results on any computer with at least
175  *  48 mantissa bits in double precision floating point data.  On Cray systems,
176  *  double precision should be disabled.
177  *
178  *  David H. Bailey     October 26, 1990
179  *
180  *     IMPLICIT DOUBLE PRECISION (A-H, O-Z)
181  *     SAVE KS, R23, R46, T23, T46
182  *     DATA KS/0/
183  *
184  *  If this is the first call to RANDLC, compute R23 = 2 ^ -23, R46 = 2 ^ -46,
185  *  T23 = 2 ^ 23, and T46 = 2 ^ 46.  These are computed in loops, rather than
186  *  by merely using the ** operator, in order to insure that the results are
187  *  exact on all systems.  This code assumes that 0.5D0 is represented exactly.
188  */
189 double randlc(double *X, double*A)
190 {
191   static int        KS=0;
192   static double  R23, R46, T23, T46;
193   double    T1, T2, T3, T4;
194   double    A1, A2;
195   double    X1, X2;
196   double    Z;
197   int       i, j;
198
199   if (KS == 0) {
200     R23 = 1.0;
201     R46 = 1.0;
202     T23 = 1.0;
203     T46 = 1.0;
204
205     for (i=1; i<=23; i++) {
206       R23 = 0.50 * R23;
207       T23 = 2.0 * T23;
208     }
209     for (i=1; i<=46; i++) {
210       R46 = 0.50 * R46;
211       T46 = 2.0 * T46;
212     }
213     KS = 1;
214   }
215
216 /*  Break A into two parts such that A = 2^23 * A1 + A2 and set X = N.  */
217   T1 = R23 * *A;
218   j  = T1;
219   A1 = j;
220   A2 = *A - T23 * A1;
221
222 /*  Break X into two parts such that X = 2^23 * X1 + X2, compute
223     Z = A1 * X2 + A2 * X1  (mod 2^23), and then X = 2^23 * Z + A2 * X2  (mod 2^46). */
224   T1 = R23 * *X;
225   j  = T1;
226   X1 = j;
227   X2 = *X - T23 * X1;
228   T1 = A1 * X2 + A2 * X1;
229
230   j  = R23 * T1;
231   T2 = j;
232   Z = T1 - T23 * T2;
233   T3 = T23 * Z + A2 * X2;
234   j  = R46 * T3;
235   T4 = j;
236   *X = T3 - T46 * T4;
237   return(R46 * *X);
238 }
239
240 void c_print_results(const char *name, char class, int n1, int n2, int n3, int niter, int nprocs_compiled,
241                      int nprocs_total, double t, double mops, const char *optype, int passed_verification)
242 {
243   printf( "\n\n %s Benchmark Completed\n", name );
244   printf( " Class           =                        %c\n", class );
245
246   if( n3 == 0 ) {
247     long nn = n1;
248     if ( n2 != 0 ) nn *= n2;
249     printf( " Size            =             %12ld\n", nn );   /* as in IS */
250   } else
251     printf( " Size            =              %3dx %3dx %3d\n", n1,n2,n3 );
252
253   printf( " Iterations      =             %12d\n", niter );
254   printf( " Time in seconds =             %12.2f\n", t );
255   printf( " Total processes =             %12d\n", nprocs_total );
256
257   if ( nprocs_compiled != 0 )
258     printf( " Compiled procs  =             %12d\n", nprocs_compiled );
259
260   printf( " Mop/s total     =             %12.2f\n", mops );
261   printf( " Mop/s/process   =             %12.2f\n", mops/((float) nprocs_total) );
262   printf( " Operation type  = %24s\n", optype);
263
264   if( passed_verification )
265     printf( " Verification    =               SUCCESSFUL\n" );
266   else
267     printf( " Verification    =             UNSUCCESSFUL\n" );
268 }