source: tests/PRNG.cfa@ 44198fb9

ast-experimental
Last change on this file since 44198fb9 was 4246869, checked in by Peter A. Buhr <pabuhr@…>, 2 years ago

update header comments

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