source: tests/PRNG.cfa @ ff7b2de

ADTast-experimentalenumpthread-emulationqualifiedEnum
Last change on this file since ff7b2de was 470618c0, checked in by Peter A. Buhr <pabuhr@…>, 2 years ago

add mutex statement for concurrent printing

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