/* gauss.c: * A complicated way of producing normal distribution plots with a * modern CPU by harvesting the intherent randomness. * * This code is striped of almost all error checking and all argument * handling - this is intended to show the prinicple only. * * compile: gcc -O2 gause.c -o gause -lpthread * run: ./gause | tee logfile * * be patient - this will take time if you want a smoth curve (hours..days !) * once you have a suitably long recording plot the distribution - brute force * might be * sort -n logfile | uniq -c > data * gnuplot * ... * gnuplot> plot "data" using 2:1 with lines * * this will give you a nice gauss cure on all systems - if it does not then * your N needs adjusting ! * * The only thing you must adjust to your hardware is N * here are some examples 32 bit: * AMD Duron UP : 12000000 * 32 bit install: * AMD Sempron UP : 5000000 * Core Duo E7400 SMP : 100000 * 64 bit intsll: * Intel Nehalem 8 core : 10000 * Intel CoreDuo 2 Quad : 5000 * * if the runs shows all samples close to 0 then increas N * if you get values all samples close to SAMPLES decrease N * * One could now speculate that this number actually is a metric for the * complexity of the CPU... * * further NUM_THREADS can be adjusted - in general 3 seems to be the best * though I have no clue why. Default 2 gives nice curves eventually as well. * if you fiddle with NUM_THREADS you also need to re-adjust N. * * what is this doing ? Its letting a set of threads race on a unprotected * global variable cnt - the run of the thread set is equivalent to drawing * a ball from an urn of infinetly many read and blue balls. If a race is * detected (cnt != N*NUM_THREADS) we assign this the color red, otherwise * blue. * The claim is that the occurance of red/blue is truely random and as evidence * this code produces close to perfect gause curves on and IDLE system. So this * is not driven by any peripheral interrupts or the like, in fact on high * loads things get a bit distorted... In my opinion this demonstrates that at * the core of a modern CPU there is in fact a true entropy source at work :) * * Copyright Der Herr Hofrat 2009,2010,2011 * License GPL V2 or later (http://www.gnu.org/copyleft/gpl.html) * * If you use this code for anything useful I would be happy to here from you ! * * thx! * hofrat */ #include /* pthread_* */ #include /* printf,perror,fflush */ #include /* exit */ #define NUM_THREADS 2 /* number of concurrent threas */ volatile long cnt = 0; /* the global object to race on */ unsigned long SAMPLES=256; /* how many balls to draw from the urn */ unsigned long NUM_TRIALS=262144; /* how many samples to draW */ unsigned long N=10000000; /* some large number - depends on hardware */ void *Thread(void *); /* This is the ESRNG that emits a ball * cnt describes the color of the ball */ void * Thread(void *v) { unsigned long n; for (n = 1; n <= N; ++n) { ++cnt; } return NULL; } /* draw the requested sampls from urn * returns number of red balls * * Note that return values of pthread_create/join * are checked as this would be critical if they failed * silent - all "unnecessary" error checking through was * removed. */ int draw_balls(int *samples){ int i,n; unsigned long red; pthread_t t[NUM_THREADS]; red=0; for(i=0;i<*samples;i++){ cnt=0; /* sample the urn */ for (n = 0; n < NUM_THREADS; ++n){ if(pthread_create( t+n, NULL, Thread, NULL)){ perror("pthread_create"); exit(-1); } } /* wait for the sample to complete */ for (n = 0; n < NUM_THREADS; ++n){ if(pthread_join(t[n],NULL)){ perror("pthread_join"); exit(-1); } } /* check the color * race occurs => red * no race => blue */ if(N*NUM_THREADS - cnt){ /* count the red */ red++; } } return red; } /* simply get NUM_TRIALS sets of balls from * the urn and print out how many were red * and how many blue - plot this to get a * nice gause curv. */ int main(int argc, char **argv) { int i; int num_red,num_blue; int sample_size=SAMPLES; i=0; while(i++