• Some users have recently had their accounts hijacked. It seems that the now defunct EVGA forums might have compromised your password there and seems many are using the same PW here. We would suggest you UPDATE YOUR PASSWORD and TURN ON 2FA for your account here to further secure it. None of the compromised accounts had 2FA turned on.
    Once you have enabled 2FA, your account will be updated soon to show a badge, letting other members know that you use 2FA to protect your account. This should be beneficial for everyone that uses FSFT.

C++/POSIX thread based program question(s)?

Kanecnc

n00b
Joined
May 16, 2007
Messages
56
Its me again. I wouldn't normally trouble people on a forum with all this but last time I posted here I got really good feedback and everyone was really helpful. So, I have created a program that uses the Monte Carlo method to find the value of pie and for the most part it works but I have a few questions.

1) I don't really understand how to use the pthread_join() function because when I implement it and try to create more than some odd threads I seg fault but if I don't put it in at all I don't seg fault.

2) I wrote the program and my professor said that it should output the value of pie and lets say I want 20 threads each thread does a process a 1000 times my value for pie should be similar to at least 8 or maybe even 10 decimal places each time I fun it but mine is not. I thought that might be to my mutex locks or my data types that I used. I am using doubles right now but Im not sure if I should use long ints instead or if it matters.

I am not asking for answers to all my problems but I am so new to POSIX threads that I am not sure what is causing me my major faults and what areas I need to check to fix my issues. I know my pthread_join isn't 100% right but I am not sure how to fix it or where to start.

So enough of me complaining below is my source code, if you would give me feed back on parts that are going to cause me issue pertaining to my 1 and 2 issues I would be very thankful. And forgive me for my messy code I have yet to clean it up.

#include <iostream>
#include <stdlib.h>
#include <pthread.h>
#include <ctime>
#include<iomanip>
using namespace std;

//Declaring Global Variables
double inside_val = 0;
double tries_total = 0;
double pi_val;
//Global Variables

pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;

struct params //Structure to pass number of iterations to threads
{
int num;
};


void * ranPtsThread(void * p) //Thread generates random points
{
params * data = (params*)p;
//Stores the value of iterations passed by the command-line
//in a local variable named iter
int iter = data->num;
int tries = 0;
double x, y, inside; //x and y values and local number of hits inside the circle


//Loop Generates number random points and test whether
//the points are inside or outside the circle
for(int i = 0; i < iter; i++)
{
pthread_mutex_lock(&mymutex); //Mutex lock
x = static_cast<double>(rand( ))/RAND_MAX; //Generates a random X value
y = static_cast<double>(rand( ))/RAND_MAX; //Generates a random y value
if((x*x + y*y) <= 1) //This would be inside the circle
{
tries++;
inside++;
}
else //Else it was a miss and not inside
{
tries++;
}

if(tries == 100 || i == (iter - 1)) //Updates the grand total inside hits
{ //and stores that to the global variable inside_val
inside_val = inside_val + inside; //
tries_total = tries_total + tries; //Updates the grand total of tries
inside = 0; //Sets the local variables inside and tries
tries = 0; //back to zero
}
pthread_mutex_unlock(&mymutex); //Mutex unlock

}
// return 0;
}



//Main Function

int main(int argc, char *argv[]) //Main function accepts two arguments, used to read
{ //in number of threads and iterations from user
srand(time(0)); //Seeds the random function
int num_threads = atoi(argv[1]); //Converting command line arguments to
int iterations = atoi(argv[2]); //integers and storing in variables
params num_iter; //Declaring num_iter as parameter
num_iter.num = iterations; //to pass iterations to threads
pthread_t TID[num_threads]; //Defining thread TID

for(int t = 0; t < num_threads; t++) //Generating number of threads defined by
{ //User
pthread_create(&TID[t], NULL, ranPtsThread, &num_iter); //Creating threads
}

//This loop joins the array of threads
/* for(int t = 0; t < num_threads; t++)
{
pthread_join(TID[t], NULL);
}
*/ pi_val = ((4*inside_val)/tries_total);

cout << setiosflags(ios::fixed|ios::showpoint) << setprecision(14) << pi_val << endl;
}
 
wrap your code in <code></code> tags (using square brackets instead of arrows) to retain formatting. it's very difficult to read otherwise. quote me for an example:

Code:
int main() {
  poo();
  return 0;
}

try passing a non-NULL argument to the second argument of pthread_join. from what im reading it uses this location to write a return value, and if its a null pointer that might be where you're getting your seg fault. could be that you can use a NULL arg to ignore the return value, but it's worth a shot.
 
Code:
#include <iostream>
#include <stdlib.h>
#include <pthread.h>
#include <ctime>
#include<iomanip>
using namespace std;

//Declaring Global Variables
double inside_val = 0; 
double tries_total = 0;
double pi_val; 
//Global Variables

pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;

struct params	//Structure to pass number of iterations to threads
{
	int num;
};


void * ranPtsThread(void * p) //Thread generates random points 
{
	params * data = (params*)p;
	//Stores the value of iterations passed by the command-line
	//in a local variable named iter
	int iter = data->num;
	int tries = 0;
	double x, y, inside;	//x and y values and local number of hits inside the circle			
	
	
	//Loop Generates number random points and test whether 
	//the points are inside or outside the circle
	for(int i = 0; i < iter; i++)
	{
		pthread_mutex_lock(&mymutex);		   //Mutex lock
		x = static_cast<double>(rand( ))/RAND_MAX; //Generates a random X value
		y = static_cast<double>(rand( ))/RAND_MAX; //Generates a random y value
		if((x*x + y*y) <= 1)			   //This would be inside the circle 
		{
			tries++;
			inside++;
		}
		else					   //Else it was a miss and not inside
		{
			tries++;
		}
	
		if(tries == 100 || i == (iter - 1))	   //Updates the grand total in inside hits
		{					   //and stores that to the global variable inside_val
			inside_val = inside_val + inside;  // 
			tries_total = tries_total + tries; //Updates the grand total of tries
			inside = 0;			   //Sets the local variables inside and tries
			tries = 0;			   //back to zero
		}
		pthread_mutex_unlock(&mymutex);		   //Mutex unlock

	}
	// return 0;
}



//Main Function

int main(int argc, char *argv[])		//Main function accepts two arguments, used to read
{						//in number of threads and iterations from user
	srand(time(0));				//Seeds the random function
	int num_threads = atoi(argv[1]);	//Converting command line arguments to 
	int iterations = atoi(argv[2]);		//integers and storing in variables
	params num_iter;			//Declaring num_iter as parameter
	num_iter.num = iterations;		//to pass iterations to threads
	pthread_t TID[num_threads];		//Defining thread TID
	
	for(int t = 0; t < num_threads; t++)	//Generating number of threads defined by  
	{					//User
		pthread_create(&TID[t], NULL, ranPtsThread, &num_iter); //Creating threads	
	}

	//This loop joins the array of threads 
/*	for(int t = 0; t < num_threads; t++)	//Loop to join threads
	{
		pthread_join(TID[t], NULL);	//(void**)&A);	
	}	
*/	pi_val = ((4*inside_val)/tries_total);

	cout << setiosflags(ios::fixed|ios::showpoint) << setprecision(14) << pi_val << endl;
}
 
Thanks for your reply! Sorry about forgetting about the code tags.

So I tried your suggestion by declaring
char * A;

and putting it in the join function like so:

pthread_join(TID[t],(void**)&A);

I got that from my notes but it didn't seem to stop the seg fault.
It seems to seg fault when i try to create 25 or plus threads.
 
This is going pretty far back for me, but let me take a shot at helping. There is a limit to the number of threads you can spawn. (What are you running this code on?) I seem to remember it being something like 3000 on my 2.6 nptl box, but I could be wrong. Write a really simple program that just makes threads, has them do something trivial, then joins them to make sure that you aren't hitting a limitation of your OS.
 
Might want to look into making your shared primitive volatile.

You also have some synchronization/mutual exclusion issues. Each thread is holding the lock for much longer than it has to. This may not necessarily produce an incorrect result, however it will result in your multi-threaded program running in a much less efficient manner. To get the least contention, you want to ensure the scope of your critical section is as small as possible by acquiring your lock at the latest possible time and releasing at the earliest possible time. You can do this by determining exactly what statement(s) have to happen mutually exclusive of each other (hint: AFAIK you NEVER need to lock any time you are only reading data, as long as this "read" has no side effects of course), e.g. the "atomic" parts of your code.
 
This is going pretty far back for me, but let me take a shot at helping. There is a limit to the number of threads you can spawn. (What are you running this code on?) I seem to remember it being something like 3000 on my 2.6 nptl box, but I could be wrong. Write a really simple program that just makes threads, has them do something trivial, then joins them to make sure that you aren't hitting a limitation of your OS.

Yeah on the server that I am doing this on they limit the number of threads that can be created to 24.

Might want to look into making your shared primitive volatile.

You also have some synchronization/mutual exclusion issues. Each thread is holding the lock for much longer than it has to. This may not necessarily produce an incorrect result, however it will result in your multi-threaded program running in a much less efficient manner. To get the least contention, you want to ensure the scope of your critical section is as small as possible by acquiring your lock at the latest possible time and releasing at the earliest possible time. You can do this by determining exactly what statement(s) have to happen mutually exclusive of each other (hint: AFAIK you NEVER need to lock any time you are only reading data, as long as this "read" has no side effects of course), e.g. the "atomic" parts of your code.

Yeah I switched those locks to just around the are where the threads edit the two global variables, i think that is the only part that really needs to be locked I believe.
 
Yeah I switched those locks to just around the are where the threads edit the two global variables, i think that is the only part that really needs to be locked I believe.

Yep. That sounds good. Are you still getting inconsistent results? Did you have a chance to try adding the "volatile" keyword to your global variable(s) which are shared?
 
Yep. That sounds good. Are you still getting inconsistent results? Did you have a chance to try adding the "volatile" keyword to your global variable(s) which are shared?

I tried the volatile and or static tags but my results are still not as precise as they need to be. At most I get a solid X.X to be the same. the rest 7 to 10 decimals are still inconsistent. Thanks for your input though I appreciated it. It might have to do with the way I am creating an joining threads but I wouldn't know how to tell the difference?
 
Yeah on the server that I am doing this on they limit the number of threads that can be created to 24.

yah if the system limits the number of threads to 24, and you try to pthread_wait() on, say, thread 25, you might get some undefined behavior (like a segfault). does it work if you limit the number of threads to 24 (after the changes you've made so far)?

i assume your precision will get better as you increase the number of threads, but since you're locked at 24 maybe you're stuck there. perhaps you might try doing a pthread_wait() directly after the thread creation...this will only spawn one thread at a time, but will allow you to scale up to however many threads you want....just to test whether or not you would be getting better results if you could spawn more than 24 threads at a time
 
yah if the system limits the number of threads to 24, and you try to pthread_wait() on, say, thread 25, you might get some undefined behavior (like a segfault). does it work if you limit the number of threads to 24 (after the changes you've made so far)?

Yeah thats what I figured, if I join a thread that doesn't exist then I presumed it would blow up. It doesn't seg fault as long as I keep the number of threads to 24 max. I didn't use pthread_wait though I used pthread_join is that bad? I am lost why I am not getting my rounding to come out the same, if I do 23 threads and run 1234 iterations of each thread I should get 8 to 10 decimal places to come out the same, according to my professor. I tired using long doubles but that didn't do anything.
 
Yeah thats what I figured, if I join a thread that doesn't exist then I presumed it would blow up. It doesn't seg fault as long as I keep the number of threads to 24 max. I didn't use pthread_wait though I used pthread_join is that bad? I am lost why I am not getting my rounding to come out the same, if I do 23 threads and run 1234 iterations of each thread I should get 8 to 10 decimal places to come out the same, according to my professor. I tired using long doubles but that didn't do anything.

For some reason when I tried to do pthread_wait() it didn't recognize it?? anywho instead I upped the iterations. like 23 threads and 1234567 and my numbers came out closer 3.141.... So you may vary well be right. I will ask my professor tomorrow to see what he thinks. Thanks for your help!

On a side note just for my own reference, am I creating my threads correctly? And when I join my threads why do I have to add some value i.e. char * A, pthread_join(TID[t], (void**)&A); if I did pthread_join(TID[t], NULL); would that be incorrect.

I just don't yet totally understand the second argument of the pthread join function and its purpose.
 
fluxion You have to be right since I am limited in the number of threads I am probably limited in my precision. I edited my program so it would print out pie every time it went through the for loop and didn't a huge number of iterations and as it goes through the precision gets better and better. So unless anyone finds something my code that they think would cause the precision to be off I think it is due to my thread cap.
 
Back
Top