source: tests/PRNG.cfa@ dd46fd3

ADT ast-experimental
Last change on this file since dd46fd3 was 20cf96d, checked in by Peter A. Buhr <pabuhr@…>, 3 years ago

changes to PRNG types to eliminate casts

  • Property mode set to 100644
File size: 6.8 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 : Tue Nov 22 22:51:12 2022
11// Update Count : 381
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
62unsigned int 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
118int main() {
119 // causes leaked storage message
120// setlocale( LC_NUMERIC, getenv( "LANG" ) ); // print digit separator
121
122 enum { TASKS = 4 };
123 Time start;
124#ifdef TIME // too slow for test and generates non-repeatable results
125#if 1
126 unsigned int rseed;
127 if ( seed != 0 ) rseed = seed;
128 else rseed = rdtscl();
129 srand( rseed );
130
131 sout | sepDisable;
132 sout | wd(13, "rand()" ) | wd(10, "rand(5)") | wd(13, "rand(0,5)" );
133 for ( 20 ) {
134 sout | wd(13, rand()) | nonl;
135 sout | wd(10, rand() % 5) | nonl;
136 sout | wd(13, rand() % (5 - 0 + 1) + 0);
137 } // for
138 sout | sepEnable;
139 sout | "seed" | rseed;
140
141 sout | nl | "Sequential";
142 STARTTIME;
143 {
144 unsigned int * buckets = calloc( BUCKETS ); // too big for task stack
145 for ( i; TRIALS / 10 ) {
146 buckets[rand() % BUCKETS] += 1; // sequential
147 } // for
148 avgstd( buckets );
149 free( buckets );
150 }
151 ENDTIME( " x 10 " );
152
153 sout | nl | "Concurrent";
154 STARTTIME;
155 {
156 processor p[TASKS - 1]; // already 1 processor
157 {
158 T1 t[TASKS];
159 } // wait for threads to complete
160 }
161 ENDTIME( " x 100 " );
162#endif // 0
163#endif // TIME
164#if 1
165 PRNG prng;
166
167 if ( seed != 0 ) set_seed( prng, seed );
168
169 sout | sepDisable;
170 sout | nl | wd(13, "PRNG()" ) | wd(10, "PRNG(5)") | wd(13, "PRNG(0,5)" );
171 for ( 20 ) {
172 sout | wd(13, prng( prng )) | nonl; // cascading => side-effect functions called in arbitary order
173 sout | wd(10, prng( prng, 5 )) | nonl;
174 sout | wd(13, prng( prng, 0, 5 ));
175 } // for
176 sout | sepEnable;
177 sout | "seed" | get_seed( prng );
178
179 sout | nl | "Sequential";
180 STARTTIME;
181 {
182 unsigned int * buckets = calloc( BUCKETS ); // too big for task stack
183 for ( TRIALS ) {
184 buckets[prng( prng ) % BUCKETS] += 1; // sequential
185 } // for
186 avgstd( buckets );
187 free( buckets );
188 }
189 ENDTIME();
190
191 sout | nl | "Concurrent";
192 STARTTIME;
193 {
194 processor p[TASKS - 1]; // already 1 processor
195 {
196 T2 t[TASKS];
197 } // wait for threads to complete
198 }
199 ENDTIME();
200#endif // 0
201#if 1
202 if ( seed != 0 ) set_seed( seed );
203
204 sout | sepDisable;
205 sout | nl | wd(13, "prng()" ) | wd(10, "prng(5)") | wd(13, "prng(0,5)" );
206 for ( 20 ) {
207 sout | wd(13, prng()) | nonl; // cascading => side-effect functions called in arbitary order
208 sout | wd(10, prng( 5 )) | nonl;
209 sout | wd(13, prng( 0, 5 ));
210 } // for
211 sout | sepEnable;
212 sout | "seed" | get_seed( prng );
213
214 sout | nl | "Sequential";
215 STARTTIME;
216 {
217 unsigned int * buckets = calloc( BUCKETS ); // too big for task stack
218 for ( TRIALS ) {
219 buckets[prng() % BUCKETS] += 1;
220 } // for
221 avgstd( buckets );
222 free( buckets );
223 }
224 ENDTIME();
225
226 sout | nl | "Concurrent";
227 STARTTIME;
228 {
229 processor p[TASKS - 1]; // already 1 processor
230 {
231 T3 t[TASKS];
232 } // wait for threads to complete
233 }
234 ENDTIME();
235#endif // 0
236#if 1
237 if ( seed != 0 ) set_seed( seed );
238 thread$ & th = *active_thread();
239
240 sout | sepDisable;
241 sout | nl | wd(13, "prng(t)" ) | wd(10, "prng(t,5)") | wd(13, "prng(t,0,5)" );
242 for ( 20 ) {
243 sout | wd(13, prng( th )) | nonl; // cascading => side-effect functions called in arbitary order
244 sout | wd(10, prng( th, 5 )) | nonl;
245 sout | wd(13, prng( th, 0, 5 ));
246 } // for
247 sout | sepEnable;
248 sout | "seed" | get_seed( prng );
249
250 sout | nl | "Sequential";
251 STARTTIME;
252 {
253 dummy( th );
254 }
255 ENDTIME();
256
257 sout | nl | "Concurrent";
258 STARTTIME;
259 {
260 processor p[TASKS - 1]; // already 1 processor
261 {
262 T4 t[TASKS];
263 } // wait for threads to complete
264 }
265 ENDTIME();
266#endif // 0
267// malloc_stats();
268} // main
269
270
271// Local Variables: //
272// compile-command: "cfa -DTIME -O2 -nodebug PRNG.cfa" //
273// End: //
Note: See TracBrowser for help on using the repository browser.