source: tests/PRNG.cfa@ 1988572

ADT ast-experimental pthread-emulation qualifiedEnum
Last change on this file since 1988572 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.