source: tests/PRNG.cfa @ 4c48be0

ADTast-experimentalpthread-emulation
Last change on this file since 4c48be0 was ee4b77b, checked in by Peter A. Buhr <pabuhr@…>, 3 years ago

allow preemption in PRNG.cfa and io/io-acquire.cfa

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