source: tests/PRNG.cfa @ 640b3df

ADTast-experimental
Last change on this file since 640b3df was ae7a085c, checked in by Peter A. Buhr <pabuhr@…>, 23 months ago

change printing format in PRNG, update .expect for tests using PRNG

  • Property mode set to 100644
File size: 7.0 KB
Line 
1//                               -*- Mode: C -*-
2//
3// Cforall Version 1.0.0 Copyright (C) 2021 University of Waterloo
4//
5// PRNG.c --
6//
7// Author           : Peter A. Buhr
8// Created On       : Wed Dec 29 09:38:12 2021
9// Last Modified By : Peter A. Buhr
10// Last Modified On : Wed Dec 21 20:39:59 2022
11// Update Count     : 406
12//
13
14#include <fstream.hfa>                                                                  // sout
15#include <stdlib.hfa>                                                                   // PRNG
16#include <clock.hfa>
17#include <thread.hfa>
18#include <limits.hfa>                                                                   // MAX
19#include <math.hfa>                                                                             // sqrt
20#include <malloc.h>                                                                             // malloc_stats
21#include <locale.h>                                                                             // setlocale
22#include <mutex_stmt.hfa>
23
24#ifdef __x86_64__                                                                               // 64-bit architecture
25#define PRNG PRNG64
26#else                                                                                                   // 32-bit architecture
27#define PRNG PRNG32
28#endif // __x86_64__
29
30#ifdef TIME                                                                                             // use -O2 -nodebug
31#define STARTTIME start = timeHiRes()
32#define ENDTIME( extra ) sout | wd(0,1, (timeHiRes() - start)`ms / 1000.) | extra "seconds"
33enum { BUCKETS = 100_000, TRIALS = 1_000_000_000 };
34#else
35#define STARTTIME
36#define ENDTIME( extra )
37enum { BUCKETS = 100_000, TRIALS = 100_000_000 };
38#endif // TIME
39
40void avgstd( unsigned int buckets[] ) {
41        unsigned int min = MAX, max = 0;
42        double sum = 0.0, diff;
43        for ( i; BUCKETS ) {
44                if ( buckets[i] < min ) min = buckets[i];
45                if ( buckets[i] > max ) max = buckets[i];
46                sum += buckets[i];
47        } // for
48
49        double avg = sum / BUCKETS;                                                     // average
50        sum = 0.0;
51        for ( i; BUCKETS ) {                                                            // sum squared differences from average
52                diff = buckets[i] - avg;
53                sum += diff * diff;
54        } // for
55        double std = sqrt( sum / BUCKETS );
56        mutex( sout ) sout | "trials"  | TRIALS | "buckets" | BUCKETS
57                | "min" | min | "max" | max
58                | "avg" | wd(0,1, avg) | "std" | wd(0,1, std) | "rstd" | wd(0,1, (avg == 0 ? 0.0 : std / avg * 100)) | "%";
59} // avgstd
60
61
62size_t seed = 1009;
63
64thread T1 {};
65void main( T1 & ) {
66        unsigned int * buckets = calloc( BUCKETS );                     // too big for task stack
67        for ( TRIALS / 100 ) {
68                buckets[rand() % BUCKETS] += 1;                                 // concurrent
69        } // for
70        avgstd( buckets );
71        free( buckets );
72} // main
73
74thread T2 {};
75void main( T2 & ) {
76        PRNG prng;
77        if ( seed != 0 ) set_seed( prng, seed );
78        unsigned int * buckets = calloc( BUCKETS );                     // too big for task stack
79        for ( TRIALS ) {
80                buckets[prng( prng ) % BUCKETS] += 1;                   // concurrent
81        } // for
82        avgstd( buckets );
83        free( buckets );
84} // main
85
86thread T3 {};
87void main( T3 & th ) {
88        unsigned int * buckets = calloc( BUCKETS );                     // too big for task stack
89        for ( TRIALS ) {
90                buckets[prng() % BUCKETS] += 1;                                 // concurrent
91        } // for
92        avgstd( buckets );
93        free( buckets );
94} // main
95
96thread T4 {};
97void main( T4 & th ) {
98        unsigned int * buckets = calloc( BUCKETS );                     // too big for task stack
99        for ( TRIALS ) {
100                buckets[prng( th ) % BUCKETS] += 1;     // concurrent
101        } // for
102        avgstd( buckets );
103        free( buckets );
104} // main
105
106// Compiler bug requires hiding declaration of th from the bucket access, otherwise the compiler thinks th is aliased
107// and continually reloads it from memory, which doubles the cost.
108static void dummy( thread$ & th ) __attribute__(( noinline ));
109static void dummy( thread$ & th ) {
110        unsigned int * buckets = (unsigned int *)calloc( BUCKETS, sizeof(unsigned int) ); // too big for task stack
111        for ( unsigned int i = 0; i < TRIALS; i += 1 ) {
112                buckets[prng( th ) % BUCKETS] += 1;                             // sequential
113        } // for
114        avgstd( buckets );
115        free( buckets );
116} // dummy
117
118
119int main() {
120        // causes leaked storage message
121        // setlocale( LC_NUMERIC, getenv( "LANG" ) );                   // print digit separator
122        // locale_t loc = newlocale( LC_NUMERIC_MASK, getenv( "LANG" ), (locale_t)0p );
123        // if ( loc == (locale_t)0p ) abort( "newlocale" );
124        // uselocale( loc );
125
126        enum { TASKS = 4 };
127        Time start;
128#ifdef TIME                                                                                             // too slow for test and generates non-repeatable results
129#if 1
130        unsigned int rseed;
131        if ( seed != 0 ) rseed = seed;
132        else rseed = rdtscl();
133        srand( rseed );
134
135        sout | sepDisable;
136        sout | wd(26, "rand()" ) | wd(12, "rand(5)") | wd(12, "rand(0,5)" );
137        for ( 20 ) {
138                sout | wd(26, rand()) | nonl;
139                sout | wd(12, rand() % 5) | nonl;
140                sout | wd(12, rand() % (5 - 0 + 1) + 0);
141        } // for
142        sout | sepEnable;
143        sout | "seed" | rseed;
144
145        sout | nl | "Sequential";
146        STARTTIME;
147        {
148                unsigned int * buckets = calloc( BUCKETS );             // too big for task stack
149                for ( i; TRIALS / 10 ) {
150                        buckets[rand() % BUCKETS] += 1;                         // sequential
151                } // for
152                avgstd( buckets );
153                free( buckets );
154        }
155        ENDTIME( " x 10 " );
156
157        sout | nl | "Concurrent";
158        STARTTIME;
159        {
160                processor p[TASKS - 1];                                                 // already 1 processor
161                {
162                        T1 t[TASKS];
163                } // wait for threads to complete
164        }
165        ENDTIME( " x 100 " );
166#endif // 0
167#endif // TIME
168#if 1
169        PRNG prng;
170
171        if ( seed != 0 ) set_seed( prng, seed );
172
173        sout | sepDisable;
174        sout | nl | wd(26, "PRNG()" ) | wd(12, "PRNG(5)") | wd(12, "PRNG(0,5)" );
175        for ( 20 ) {
176                sout | wd(26, prng( prng )) | nonl;                             // cascading => side-effect functions called in arbitary order
177                sout | wd(12, prng( prng, 5 )) | nonl;
178                sout | wd(12, prng( prng, 0, 5 ));
179        } // for
180        sout | sepEnable;
181        sout | "seed" | get_seed( prng );
182
183        sout | nl | "Sequential";
184        STARTTIME;
185        {
186                unsigned int * buckets = calloc( BUCKETS );             // too big for task stack
187                for ( TRIALS ) {
188                        buckets[prng( prng ) % BUCKETS] += 1;           // sequential
189                } // for
190                avgstd( buckets );
191                free( buckets );
192        }
193        ENDTIME();
194
195        sout | nl | "Concurrent";
196        STARTTIME;
197        {
198                processor p[TASKS - 1];                                                 // already 1 processor
199                {
200                        T2 t[TASKS];
201                } // wait for threads to complete
202        }
203        ENDTIME();
204#endif // 0
205#if 1
206        if ( seed != 0 ) set_seed( seed );
207
208        sout | sepDisable;
209        sout | nl | wd(26, "prng()" ) | wd(12, "prng(5)") | wd(12, "prng(0,5)" );
210        for ( 20 ) {
211                sout | wd(26, prng()) | nonl;                                   // cascading => side-effect functions called in arbitary order
212                sout | wd(12, prng( 5 )) | nonl;
213                sout | wd(12, prng( 0, 5 ));
214        } // for
215        sout | sepEnable;
216        sout | "seed" | get_seed( prng );
217
218        sout | nl | "Sequential";
219        STARTTIME;
220        {
221                unsigned int * buckets = calloc( BUCKETS );             // too big for task stack
222                for ( TRIALS ) {
223                        buckets[prng() % BUCKETS] += 1;
224                } // for
225                avgstd( buckets );
226                free( buckets );
227        }
228        ENDTIME();
229
230        sout | nl | "Concurrent";
231        STARTTIME;
232        {
233                processor p[TASKS - 1];                                                 // already 1 processor
234                {
235                        T3 t[TASKS];
236                } // wait for threads to complete
237        }
238        ENDTIME();
239#endif // 0
240#if 1
241        if ( seed != 0 ) set_seed( seed );
242        thread$ & th = *active_thread();
243
244        sout | sepDisable;
245        sout | nl | wd(26, "prng(t)" ) | wd(12, "prng(t,5)") | wd(12, "prng(t,0,5)" );
246        for ( 20 ) {
247                sout | wd(26, prng( th )) | nonl;                               // cascading => side-effect functions called in arbitary order
248                sout | wd(12, prng( th, 5 )) | nonl;
249                sout | wd(12, prng( th, 0, 5 ));
250        } // for
251        sout | sepEnable;
252        sout | "seed" | get_seed( prng );
253
254        sout | nl | "Sequential";
255        STARTTIME;
256        {
257                dummy( th );
258        }
259        ENDTIME();
260
261        sout | nl | "Concurrent";
262        STARTTIME;
263        {
264                processor p[TASKS - 1];                                                 // already 1 processor
265                {
266                        T4 t[TASKS];
267                } // wait for threads to complete
268        }
269        ENDTIME();
270#endif // 0
271//      malloc_stats();
272        // freelocale( loc );
273} // main
274
275
276// Local Variables: //
277// compile-command: "cfa -DTIME -O2 -nodebug PRNG.cfa" //
278// End: //
Note: See TracBrowser for help on using the repository browser.