I am beginner in multi thread programming. I have a homework, which I should create some number of thread (in my case 10) and generate a random number inside of each one.
when I debug my code (or put 'sleep(1)' command) it works correctly, otherwise the generated values are not equal anymore.
please help me and explain me if you think there is something which I still did'nt understand it.
The code:
#include<stdio.h>
#include<pthread.h>
#include<time.h>
int rn, sharedArray[10];
pthread_mutex_t lock;
int randomgenerator(){
//sleep(1);
srand(time(NULL)); // The value of random depend on the time with some changes in the time library
int rn, MAX = 10; // between 0 and 10
rn = rand()%MAX;
return rn;
}
void *rgen(void *arg){
int order = (int*)arg;
//pthread_mutex_lock(&lock);
int rn = randomgenerator();
printf("%d,%d\n", order,rn); //not working without printf why????
sharedArray[order]= rn;
//pthread_mutex_unlock(&lock);
pthread_exit(NULL);
}
void main(int argc, char *argv[]){
pthread_mutex_init(&lock, NULL);
pthread_t th[10];
int i;
for (i = 0; i <10; i ++){
pthread_create(&(th[i]), 0, rgen, (void *)i);
pthread_join(th[i], NULL);
}
int j, result = 0;
for (j=0; j<10; j++){
result = sharedArray[j] + result;
}
printf("the final result is: %d\n",result);
pthread_exit(NULL);
pthread_mutex_destroy(&lock);
}
And the output is:
0,3
1,3
2,3
3,3
4,3
5,3
6,3
7,3
8,3
9,3
the final result is: 30
The output which I expect with uncommenting the sleep is:
0,7
1,4
2,1
3,8
4,5
5,2
6,9
7,6
8,3
9,0
the final result is: 45
The problem is this line:
srand(time(NULL));
The man page for rand/srand says:
The srand() function sets its argument as the seed for a new sequence of pseudo-random integers to be returned by rand(). These sequences are repeatable by calling srand() with the same seed value.
You set a new seed every time. That is wrong! You should only call srand once.
When you comment out the sleep, all threads set the same seed and then gets the first random number in that sequence. If they do it in the same second, they each get the same random value.
Solution:
Move the call to srand to main, before you create any threads.
Note:
The function rand() is not reentrant or thread-safe, since it uses hidden state that is modified on each call.
That means that you cannot safely call rand simultaneously from multiple threads. You should either protect the call by using a mutex or semaphore, or switch to a reentrant function, like rand_r.
Related
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.
I created a program that does the addition of 8 numbers using 4 threads, and then the product of the results. How to ensure that each thread is using a separate core for maximum performance gains. I am new to pthreads so I really don't have any idea on how to use it properly. Please provide answers as simple as possible.
My code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int global[9];
void *sum_thread(void *arg)
{
int *args_array;
args_array = arg;
int n1,n2,sum;
n1=args_array[0];
n2=args_array[1];
sum = n1*n2;
printf("N1 * N2 = %d\n",sum);
return (void*) sum;
}
void *sum_thread1(void *arg)
{
int *args_array;
args_array = arg;
int n3,n4,sum2;
n3=args_array[2];
n4=args_array[3];
sum2=n3*n4;
printf("N3 * N4 = %d\n",sum2);
return (void*) sum2;
}
void *sum_thread2(void *arg)
{
int *args_array;
args_array = arg;
int n5,n6,sum3;
n5=args_array[4];
n6=args_array[5];
sum3=n5*n6;
printf("N5 * N6 = %d\n",sum3);
return (void*) sum3;
}
void *sum_thread3(void *arg)
{
int *args_array;
args_array = arg;
int n8,n7,sum4;
n7=args_array[6];
n8=args_array[7];
sum4=n7*n8;
printf("N7 * N8 = %d\n",sum4);
return (void*) sum4;
}
int main()
{
int sum3,sum2,sum,sum4;
int prod;
global[0]=9220; global[1]=1110; global[2]=1120; global[3]=2320; global[4]=5100; global[5]=6720; global[6]=7800; global[7]=9290;// the input
pthread_t tid_sum;
pthread_create(&tid_sum,NULL,sum_thread,global);
pthread_join(tid_sum,(void*)&sum);
pthread_t tid_sum1;
pthread_create(&tid_sum1,NULL,sum_thread1,global);
pthread_join(tid_sum1,(void*)&sum2);
pthread_t tid_sum2;
pthread_create(&tid_sum2,NULL,sum_thread2,global);
pthread_join(tid_sum2,(void*)&sum3);
pthread_t tid_sum3;
pthread_create(&tid_sum3,NULL,sum_thread3,global);
pthread_join(tid_sum3,(void*)&sum4);
prod=sum+sum2+sum3+sum4;
printf("The sum of the products is: %d", prod);
return 0;
}
You don't have, don't want and mustn't (I don't know if you somehow you can though) manage hardware resources at such low levels. That's a job for your OS and partially for standard libraries: they have been tested optimized and standardized properly.
I doubt you can do better. If you do what you are saying either you are an expert hardware/OS programmer or you are destroying decades of works :) .
Also consider this fact: your code will not be portable anymore if you could index the cores manually since it depends on the number of cores of your machine.
On the other way multithread programs should work (and even better sometimes) even when having one core. An example is the case where one of the threads doesn't do anything until an event happens: you can make one thread go to "sleep" so that only the other threads use the CPU; then when the event happens it will execute. In a non-multithread program generally polling is used which uses CPU resource to do nothing.
Also #yano said you are multithread program is not really parallel in this case since you are creating the thread and then waiting for it to finish with pthread_join before starting the other threads.
Below is my C code to print an increasing global counter, one increment per thread.
#include <stdio.h>
#include <pthread.h>
static pthread_mutex_t pt_lock = PTHREAD_MUTEX_INITIALIZER;
int count = 0;
int *printnum(int *num) {
pthread_mutex_lock(&pt_lock);
printf("thread:%d ", *num);
pthread_mutex_unlock(&pt_lock);
return NULL;
}
int main() {
int i, *ret;
pthread_t pta[10];
for(i = 0; i < 10; i++) {
pthread_mutex_lock(&pt_lock);
count++;
pthread_mutex_unlock(&pt_lock);
pthread_create(&pta[i], NULL, (void *(*)(void *))printnum, &count);
}
for(i = 0; i < 10; i++) {
pthread_join(pta[i], (void **)&ret);
}
}
I want each thread to print one increment of the global counter but they miss increments and sometimes access same values of global counter from two threads. How can I make threads access the global counter sequentially?
Sample Output:
thread:2
thread:3
thread:5
thread:6
thread:7
thread:7
thread:8
thread:9
thread:10
thread:10
Edit
Blue Moon's answer solves this question. Alternative approach is available in MartinJames'es comment.
A simple-but-useless approach is to ensure thread1 prints 1, thread2 prints 2 and so on is to put join the thread immmediately:
pthread_create(&pta[i], NULL, printnum, &count);
pthread_join(pta[i], (void **)&ret);
But this totally defeats the purpose of multi-threading because only one can make any progress at a time.
Note that I removed the superfluous casts and also the thread function takes a void * argument.
A saner approach would be to pass the loop counter i by value so that each thread would print different value and you would see threading in action i.e. the numbers 1-10 could be printed in any order and also each thread would print a unique value.
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.
Is there a way to generate a number number between two limits without using the sran and rand function
What it is that i have a while (1) (super loop) which calls a function every 10 ms seconds. in the function a for loop is used to create a delay, but, everytime the function is access the delay should be different but between two limts, 8 and 2 ms, for(x=0;x<random_number;x++)
Try bellow hope this will answer your question.
#include<stdio.h>
#include <stdlib.h>
int main()
{
int iMaxRand =100,ii=0 ;
while( ii < 100)
{
printf("Random Number is:%d\n", rand() % iMaxRand);
ii++;
}
printf("\n");
}