source: tests/PRNG.cfa @ 7358f65

ADTast-experimental
Last change on this file since 7358f65 was e6d8d11, checked in by Peter A. Buhr <pabuhr@…>, 14 months ago

update comment about locale problem with leaked storage

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