time dependent uniformly distributed random number - c

I need a uniformly distributed random number generator...
Here is what I've tried its output is a constant number no matter how many time i run the .exe
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int randr( int min, int max);
int main()
{
srand(time(NULL));
int rr=randr(0,10);
printf("rr=%d\n",rr)
return 0;
}
int randr( int min, int max)
{
double scaled = (double)rand()/RAND_MAX;
return (max - min +1)*scaled + min;
}
Thanks in advance.

The problem with your code is that the time function doesn't use milliseconds, so each call to your function set the same seed and generate the same first number (assuming it's called at the same time, i.e. the same second).
One way to avoid this is to give a seed only once in your program (srand must be called only once), you can verify that by trying this code :
int main()
{
int a = 0;
srand(time(NULL));
for (int i=0;i<10000;i++){
int rr=randr(0,10);
a+=rr;
printf("rr=%d\n",rr);
}
printf("mean : %d\n", a/10000); // to quickly check the uniformity
return 0;
}
Another way is to use a function that can give you a different seed at each call (time based on milliseconds for example). A possible implementation on a POSIX system :
struct timespec tmp;
clock_gettime(CLOCK_MONOTONIC,&tmp);
srand(tmp.tv_nsec);
This will be based on nanoseconds (as suggested by R..), to compile you'll probably need to link with librt (-lrt on gcc).

Related

Unable to figure out where the race condition occuring In OPENMP program in c

I am trying to integrate sin(x) from 0 to pi. But every time i run
the program i am getting different outputs.I know it is because of race condition occuring , but i am unable to figure out where is the problem lies
this is my code:
#include<stdio.h>
#include<stdlib.h>
#include<omp.h>
#include<math.h>
#include<time.h>
#define NUM_THREADS 4
static long num_steps= 10000000;
float rand_generator(float a )
{
//srand((unsigned int)time(NULL));
return ((float)rand()/(float)(RAND_MAX)) * a;
}
int main(int argc, char *argv[])
{
// srand((unsigned int)time(NULL));
omp_set_num_threads(NUM_THREADS);
float result;
float sum[NUM_THREADS];
float area=3.14;
int nthreads;
#pragma omp parallel
{
int id,nthrds;
id=omp_get_thread_num();
sum[id]=0.0;
printf("%d\n",id );
nthrds=omp_get_num_threads();
printf("%d\n",nthrds );
//if(id==0)nthreads=nthrds;
for (int i = id; i < num_steps; i=i+nthrds)
{
//float y=rand_generator(1);
//printf("%f\n",y );
float x=rand_generator(3.14);
sum[id]+=sin(x);
}
//printf(" sum is: %lf\n", sum);
//float p=(float)sum/num_steps*area;
}
float p=0.0;
for (int i = 0; i <NUM_THREADS; ++i)
{
p+=(sum[i]/num_steps)*area;
}
printf(" p is: %lf\n",p );
}
I tried adding pragma atomic but it also doesn't help.
Any help will be appreciated :).
The problem comes from the use of rand(). rand() is not thread safe. The reason is that it uses a common state for all the calls and is thus sensitive to races. Using stdlib's rand() from multiple threads
There a thread safe random generator that is called rand_r(). Instead of storing the rand generator state in an hidden global var, the state is a parameter to the function and can be rendered thread local.
You can use it like that
float rand_generator_r(float a,unsigned int *state )
{
//srand((unsigned int)time(NULL));
return ((float)rand_r(state)/(float)(RAND_MAX)) * a;
}
In your parallel block, add :
unsigned int rand_state=id*time(NULL); // or whatever thread dependent seed
and in your code call
float x=rand_generator(3.14,&rand_state);
and it should work.
By the way, I have the impression that there is a false sharing in your code that should slow down performances.
float sum[NUM_THREADS];
It is modified by all threads and is really likely to be store in a single cache line. Every store (and there are many stores to it) will create an invalidate in all other caches and it may significantly slow down your performances.
You should insure that the values are in different cache lines with :
#define CACHE_LINE_SIZE 64
struct {
float s;
char padding[CACHE_LINE_SIZE - sizeof(float)];
} sum_nofalse_sharing[NUM_THREADS];
and in your code, accumulate in sum_nofalse_sharing[id].s
Alternatively, create a local sum in the parallel block and write its value to sum[id] at the end.

Working example Intel RdRand in C language. How to generate a float type number in the range -100.001 through +100.001

There is an Intel DRNG Library that allows you to use a random number generator based on the processor's crystal entropy effect.
The library itself and an instruction of its use: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-library-implementation-and-uses
There is an example inside a library that just prints the contents of a randomly generated array.
Please, share the working example in C, which allows using this library to generate a float type number in the range -100.001 through +100.001
I was able to find only a code, based on the pseudo-random number generator, but it is not what I need:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
float randoms(float min, float max)
{
return (float)(rand())/RAND_MAX*(max - min) + min;
}
int main()
{
srand((unsigned int)time(0));
printf("%f\n",randoms(-100.001, 100.001));
return 0;
}
Thanks in advance.
The answer have been posted on the Intel's DRNG page not long ago. I would like to cite it here:
You can almost use that same algorithm. You just need a way to check
for the (highly unlikely) chance the RDRAND instruction will not
return a value.
Here's how I would modify your code snippet for Linux (you'll need to
supply the -mrdrnd option to gcc to compile this):
#include <stdio.h>
#include <limits.h>
char randoms(float *randf, float min, float max)
{
int retries= 10;
unsigned long long rand64;
while(retries--) {
if ( __builtin_ia32_rdrand64_step(&rand64) ) {
*randf= (float)rand64/ULONG_MAX*(max - min) + min;
return 1;
}
}
return 0;
}
int main()
{
float randf;
if ( randoms(&randf, -100.001, 100.001) ) printf("%f\n", randf);
else printf("Failed to get a random value\n");
return 0;
}
See section 4.2.1 in the above document:
4.2.1 Retry Recommendations
It is recommended that applications attempt 10 retries in a tight loop
in the unlikely event that the RDRAND instruction does not return a
random number. This number is based on a binomial probability
argument: given the design margins of the DRNG, the odds of ten
failures in a row are astronomically small and would in fact be an
indication of a larger CPU issue.

adding a number to the computer's time

This is a program that prints the current time. how do i add numbers to the time printed. Example: the output of the program is 15:35. how do i make it print 16:35? if this isn't possible; i would like to know if they are any other methods i can use. thanks
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void main()
{
FILE *fp;
char hc1,hc2,mc1,mc2;
int hi1,hi2,mi1,mi2,hour,minute;
system("echo %time% >time.txt");
fp=fopen("time.txt","r");
if(fp==NULL)
exit(1) ;
hc1=fgetc(fp);
hc2=fgetc(fp);
fgetc(fp);
mc1=fgetc(fp);
mc2=fgetc(fp);
fclose(fp);
remove("time.txt");
hi1=hc1;
hi2=hc2;
mi1=mc1;
mi2=mc2;
hi1-=48;
hi2-=48;
mi1-=48;
mi2-=48;
hour=hi1*10+hi2;
minute=mi1*10+mi2;
printf("the Current time is %d:%d\n",hour,minute);
}
If you are writing an application for getting current system time and performing arithmetic operation on it, a better way is to use the timeval struct in C.
It is present in the "sys/time.h" header and stores the time in both seconds and microseconds format. Also, it has got the gettimeofday() function to get current system time.
Following are the links for your reference:
Timeval struct
gettimeofday() function
NOTE: Some of the functions used with this struct are not portable and may work only on Linux based systems.
Add integers directly to your hour or minute variables similar to the two different ways here:
hour += 1;
hour = hour + 1;
Or do the literal addition in your `printf,
printf("the Current time is %d:%d\n",hour + 1,minute);
As David commented below, be mindful of pushing the hour or minute past 23 or 59, respectively.
check this simple function
void AddTime(int& currentH, int& currentM, int& currentS, int addH, int addM, int addS)
{
int extraM=(currentS+addS)/60;
currentS=(currentS+addS)%60;
int extraH=(currentM+addM+extraM)/60;
currentM=(currentM+addM+extraM)%60;
int extraD=(currentH+addH+extraH)/24;
currentH=(currentH+addH+extraH)%24;
}

Program doesn't work when rrun normally, but with debug step by step the result is right

In the code below, which I wrote on visual studio 2013, I pressed Ctrl+F5 but don't print the right result, I debug it step by step the results is right.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
int randfoo(void)
{
time_t ts;
int a[10];
unsigned int randdata = time(&ts);
srand(randdata);
return (rand() % 100);
}
int randNumber(int firstNum, int lastNumber, int result[][6])
{
int ret_val = -1;
int value1;
if ((firstNum > 0) && (firstNum < 5))
{
if ((lastNumber>0) && (lastNumber < 7))
{
for (int i = 0; i < firstNum; i++)
{
for (int j = 0; j < lastNumber; j++)
{
value1 = randfoo();
result[i][j] = value1;
printf("a[%d][%d]=%d\n", i, j, result[i][j]);
}
}
ret_val = 0;
}
else
{
ret_val = -1;
}
}
else
{
ret_val = -1;
}
return ret_val;
}
void main()
{
int buff[4][6];
randNumber(4, 6, buff);
system("pause");
}
the first function randfoo just to generate a rand number.
the second function randNumber in order to put the rand number into the result[4][6],and print the results.
You used srand(randdata); on each call to randfoo(). srand() is used to seed the PRNG for rand(). You don't seed it every time.
Just use srand(randdata) once in main() and rand() % 100 directly in all the assignments.
You can get rid of the whole randfoo() function, IMHO.
Random wont be random enough if you access it again and again repeatedly in the time of CPU cycles. To read more about rand please read this page.
The period of rand is implementation defined, but typically falls
around 2^32-1. Compare this with the Mersenne Twister algorithm, which
is 2^19937-1. You typically want the period of a random number
generator to exceed the amount of numbers expected to be generated,
because that's the point where the sequence repeats.
From another answer in SO (source link):
Don't call srand before every call to rand. Call it once when your
program starts.
You may want to look at this SO question.
It may be useful to explain the reason it "works" when you debug it and "doesn't work" when you run it.
When you run it normally it executes in much less time than 1 second. Thus, the time() function always returns the same time (unless you get very lucky and run it exactly on a second boundary) and thus you call srand() with the same value and so rand() returns the same value for each call to randfoo().
When you debug it, however, it probably takes a few seconds between calls to randfoo() thus you get different time() values, which seeds the pseudo-random generator with different values, and thus different rand() values.
A great example of a Heisenbug, a bug that disappears when you try to find it. The solution, as the other answers say, is to simply call srand() once at the program start.

Get average run-time of a C program

I'm trying to measure differences in speed of reading and writing misaligned vs aligned bits into binary files. I would like to know is there an utility I can use (Except for running time over & over again and writing my own) to sample an average run-time of a program (I'm running Linux based OS)?
Thanks
running time over & over again and writing my own
That's fine. You can perform the read/write ten thousand times both ways and compute the average time.
If you really want to use a library you can try Google Perftools.
Put this in a header file:
#ifndef TIMER_H
#define TIMER_H
#include <stdlib>
#include <sys/time.h>
typedef unsigned long long timestamp_t;
static timestamp_t
get_timestamp ()
{
struct timeval now;
gettimeofday (&now, NULL);
return now.tv_usec + (timestamp_t)now.tv_sec * 1000000;
}
#endif
Include the header file into whichever .c file you'll be using, and do something like this:
#define N 10000
int main()
{
int i;
double avg;
timestamp_t start, end;
start = get_timestamp();
for(i = 0; i < N; i++)
foo();
end = get_timestamp();
avg = (end - start) / (double)N;
printf("%f", avg);
return 0;
}
Basically this calls whichever function you're trying to measure performance of N times, where N is a defined constant (doesn't have to be) in this case. It takes a timestamp before the for loop and after the for loop and then calculates the average time it's taken for the function to execute. The get_timestamp() function returns the number of microseconds, so if you need milliseconds, divide by 1000, seconds - divide by 1000000 etc.

Resources