I am trying to write a C program that makes use of pThreads. This particular program creates multiple threads (1 to maxNumber) and does something with them (in the method threadMethod). I pass a struct Arguments to the pThread creator that contains necessary information about the threads, and threadNumber is included in that struct. I am trying to make the program print which thread is doing work at that moment, but when I run the program, it always prints maxNumber instead of threadNumber. For example, if I want to make 3 threads, I should have an output like:
I am thread 1
I am thread 2
I am thread 3
But instead of the above, I get an output like:
I am thread 3
I am thread 3
I am thread 3
What is going wrong with my program? I have a feeling it has something to do with the struct, but I am not certain. Below is the relevant code.
Arguments *arg = malloc(sizeof(Arguments));
int i;
for (i = 0; i < maxNumber; i++) {
arg->threadNumber = (i + 1); /* eg. first thread is Thread 1, not Thread 0 */
if (pthread_create(&threads[i], NULL, threadMethod, (void *)arg)) {
printf("Error while creating thread\n");
return 1;
}
}
--------------------
void *threadMethod(void *arg) {
Arguments *argument;
int threadNumber;
argument = (Arguments*)arg;
threadNumber = argument->threadNumber;
printf("I am thread %d\n", threadNumber);
/* do stuff */
return NULL;
}
All your threads are sharing a single arg object, because you are only allocating it once. Move the malloc() inside the loop.
Related
I have to do partial sums using parallel reduction approach in C. but I doesn't have any idea about it. So, I need guidance of Community to achieve this.
What I need to achieve: for example, computational thread, then in first reduction step add two element in array, thread 4 should wait for thread 0 done, same as thread 5 has to wait for thread 1 done, thread 6 waits for thread 2 & thread 7 should waits for thread 3 done .
now in second step, , thread 6 waits for thread 4 finished, and thread 7 waits for thread 5 finished. , thread 6 waits for thread 4 finished, and thread 7 waits for thread 5 finished.
In the third step, thread 7 waits for thread 6 done. then need to print whole array
Please help me, give me a guidance to achieve this one.
The Intel oneTBB library include "parallel_reduce" algorithm, which can be used directly for such task.
https://spec.oneapi.io/versions/latest/elements/oneTBB/source/algorithms/functions/parallel_reduce_func.html
Since oneTBB only support C++, if only C can be used, you could consider to use OpenMP instead. But it also need toolchain support.
https://www.intel.com/content/www/us/en/develop/documentation/advisor-user-guide/top/model-threading-designs/add-parallelism-to-your-program/replace-annotations-with-openmp-code/openmp-reduction-operations.html
I'm confused about how to manage computing thread a given thread should wait. 2^r-i, where r = log(m).
There are at least two easy ways to do that:
save all thread-ids in a global pthread_t ptid[N]; array.
save all thread-ids in a local pthread_t ptid[N]; array, and pass the address of that array into each thread via the thread argument.
Example pseudo-code for the latter (error handling omitted for clarity):
struct Arg {
pthread_t *ptid; // Address of ptid[N].
int idx; // Index of this thread.
};
void *partial_sum(void *p)
{
struct Arg *arg = (struct Arg *)p;
int sum = 0;
... // Compute my portion of the partial sum.
int other_thread_idx = ...; // Compute index of the other thread
// this thread should join, -1 if none.
if (other_thread_idx >= 0) {
int other_sum;
// Get the result from other thread.
pthread_join(arg->ptid[other_thread_idx], (void*) &other_sum);
printf("Thread %d joined thread %d which returned sum %d\n",
arg->idx, other_thread_idx, other_sum);
sum += other_sum;
}
printf("Thread %d, sum: %d\n", sum);
return (void*) sum;
}
int main()
{
struct Arg args[N];
pthread_t ptid[N];
for (int i = 0; i < N; ++i) {
struct Arg* arg = &args[i];
arg->idx = i;
arg->ptid = &ptid[0];
pthread_create(&ptid[i], partial_sum, NULL, arg);
}
// Get the final result.
int sum;
// Note: joining only the last thread -- all others have been joined
// already.
pthread_join(ptid[N - 1], (void*) &sum);
printf("Sum: %d\n", sum);
return 0;
}
I am learning the basics of POSIX threads. I want to create a program that prints "Hello World!" 10 times with a delay of a second between each printout. I've used a for loop to print it 10 times, but I am stuck on how to implement the time delay part.
This is my code so far:
#define MAX 10
void* helloFunc(void* tid)
{
printf("Hello World!\n", (int)(intptr_t)tid);
}
int main(int ac, char * argv)
{
pthread_t hej[MAX];
for (int i = 0; i < MAX; i++)
{
pthread_create(&hej[i], NULL, helloFunc, (void*)(intptr_t)i);
pthread_join(&hej[i], NULL);
}
pthread_exit(NULL);
return(0);
}
Thanks in advance!
There are two major problems with your code:
First of all you must wait for the threads to finish. You do that by joining them with pthread_join. And for that to work you must save the pthread_t value from each and every thread (for example in an array).
If you don't wait for the threads then the exit call will end the process, and that will also unexpectedly kill and end all threads in the process.
For all threads to run in parallel you should wait in a separate loop after you have created them:
pthread_t hej[MAX];
for (int i = 0; i < MAX; i++)
{
pthread_create(&hej[i], ...);
}
for (int i = 0; i < MAX; i++)
{
pthread_join(&hej[i], NULL);
}
The second problem is that you pass a pointer to i to the thread, so tid inside the thread functions will be all be the same (and a very large and weird value). To pass a value you must first cast it to intptr_t and then to void *:
pthread_create(..., (void *) (intptr_t) i);
And in the thread function you do the opposite casting:
printf("Hello World %d!\n", (int) (intptr_t) tid);
Note that this is an exception to the rule that one should never pass values as pointers (or opposite).
Finally for the "delay" bit... On POSIX systems there are many ways to delay execution, or to sleep. The natural and simple solution would be to use sleep(1) which sleeps one second.
The problem is where do to this sleep(1) call. If you do it in the thread functions after the printf then all threads will race to print the message and then all will sleep at the same time.
If you do it in the loop where you create the threads, then the threads won't really run in parallel, but really in serial where one thread prints it message and exits, then the main thread will wait one second before creating the next thread. It makes the threads kind of useless.
As a possible third solution, use the value passed to the thread function to use as the sleep time, so the thread that is created first (when i == 0) will primt immediately, the second thread (when i == 1) will sleep one second. And so on, until the tenth thread is created and will sleep nine seconds before printing the message.
Could be done as:
void* helloFunc(void* tid)
{
int value = (int) (intptr_t) tid;
sleep(value);
printf("Hello World %d!\n", value);
// Must return a value, as the function is declared as such
return NULL;
}
I'm trying to create several thread workers in a function called engine_setup, but every time the function returns, every thread stops as well. I tried to create pthread id as global pointer but didn't help.
here's the global:pthread_t * threadIDs;
the engine_setup function:
query_helper* engine_setup(size_t n_processors) {
//some code that is not relevant
int err;
threadIDs=malloc(n_processors*sizeof(*threadIDs));
for(int i=0;i<n_processors;i++){
err = pthread_create(&threadIDs[i],NULL,tp,(void*)helper);
if (err != 0)
printf("can't create thread \n");
}
printf("end setup\n");
return helper;
}
and the thread function pointer is here:
void* tp(void * ptr){
query_helper * helper=(query_helper*)ptr;
while(1){
printf("1\n");
}
}
the output is something like this:
1
1
1
1
1
1
1
1
1
end setup
which shows that all the threads stopped when engine_setup return. Is there a way to keep them running?
Does your program exit after the function returns? If so you'd want to use pthread_join on each thread so that the program will wait for each thread to terminate before exiting.
Yes, you can call pthread_join(threadIds[i],null); (for all threads i), which will wait until the thred function returns.
You can use the second argument for storing return value from thread.
I.e:
void *results[n_processors];
for(int i=0; i<n_processors; i++){
pthread_join(threadIds[i], &results[i]);
}
I am working on this problem: take from the command line a letter and the name of same files, count the occurrence of the char in each file, using one thread per file, and and print the total occurrences.
This is my code:
typedef struct _CharFile{
char c;
char *fileName;
} CharFile;
pthread_mutex_t count = PTHREAD_MUTEX_INITIALIZER;
int sum = 0;
void *CountFile(void *threadarg);
int main(int argc, const char * argv[]) {
pthread_t threads[argc-2];
int chck, t;
CharFile cf;
for ( t=0 ; t<argc-2 ; t++ ){
cf.c = argv[1][0];
cf.fileName = (char *)argv[t + 2];
chck = pthread_create(&threads[t], NULL, CountFile, (void *) &cf);
if (chck){
printf("ERROR; return code from pthread_create() is %d\n", chck);
exit(-1);
}
}
printf("%lld occurrences of the letter %c in %lld threads\n", (long long)sum, argv[1][0], (long long)argc-2);
return 0;
}
void *CountFile(void *threadarg){
FILE *in;
CharFile *cf;
char c;
int counter = 0;
cf = (CharFile *) threadarg;
in = fopen(cf->fileName, "r");
if (in == NULL){
perror("Error opening the file!\n");
pthread_exit(NULL);
}
while (fscanf(in, "%c", &c) != EOF){
if(c == cf->c){
counter += 1;
}
}
fclose(in);
pthread_mutex_lock(&count);
sum += counter;
pthread_mutex_unlock(&count);
pthread_exit(NULL);
}
I don't get any error in the file opening or in the thread creations, but my output is always 0 as total occurrences. I also tried to print the counter in the threads and I got every time the same numbers in all the threads, even if my input files are different. Am I using the mutex wrongly or is there something else wrong?
This is one of my outputs:
61 occurrences of e in this thread
0 occurrences of the letter e in 3 threads
61 occurrences of e in this thread
61 occurrences of e in this thread
Program ended with exit code: 9
There are several threading issues at play here.
1) The main thread will continue asynchronously to the newly spawned threads. Given the code, it is very likely that the main thread will complete and exit before the CountFile threads have completed. On Linux, when the main thread returns, the C runtime will perform a exit_group system call which will terminate all threads.
You'll need to add some check to ensure the CountFile threads have finished the relevant section of work. In this example, look at using pthread_join() in the main thread.
2) The 'cf' storage in the main thread is a stack local variable, which is passed by pointer to each thread. However, since it is the same storage, several types of failures could occur. a) the workunit may be updated by the main thread while a worker thread is accessing it. b) the same workunit is sent to multiple/all threads.
You could solve this several ways: 'cf' could be an array of CharFile for each thread. Or 'cf' could be dynamically allocated for each thread. The former is a bit more performance and memory efficient, but the later might be better structurally. Particularly that main thread is giving addresses in its local stack space to another thread.
3) Once item #1 is addressed and the threads exited before the main thread printf, the mutex usage would be ok. But it might be better to put pthread_mutex_locks around the main thread access of 'sum' anyway. It may not be necessary given this code, but future code refactors might change that.
I'm learning about threads now. I'm wondering if it is possible to pass a variable to my thread. My assignement is to create a thread and assign a number (a name if you will) to each thread and print the number every 100ms. my current program is as below :
#define PCHECK(sts,msg) if((sts)!=0){printf("error : %s\n",msg); exit(EXIT_FAILURE)}
#define NB_THREAD 5
void* do_nothing(void* data)
{
int i;
//printf("creation thread %d",(int)data);
while(1)
{
usleep(100000);
printf("thread number : %d \n",data);
}
i = 0;
pthread_exit(NULL);
//exit(EXIT_SUCCESS);
}
int main(int argc, char *argv[])
{
int pid, j, status;
pthread_t thread;
int * res;
int stat;
for (j = 0; j < NB_THREAD; j++)
{
stat = pthread_create(&thread, NULL, do_nothing, (void *) j );
if (stat !=0)
{
perror ("pthread_create()");
}
}
for (j = 0; j < NB_THREAD; j++)
{
pthread_join(thread, (void **) &res );
}
return EXIT_SUCCESS;
}
for the moment the only number getting printed is 0 (the value of data). Can someone point out where did i went wrong thanks :)
Here are some good examples of how to pass arguments to pthreads
[1] https://computing.llnl.gov/tutorials/pthreads/#PassingArguments
I suspect that your problem might be that your running this on a 64-bit system that uses 32-bit int types. So data is a 64-bit void* type but in your thread function you're printing it out as a 32-bit int:
// example assumes that this thread instance was started by
// pthread_create(&thread, NULL, do_nothing, (void *) j ) when
// j == 1
printf("thread number : %d \n",data);
^ ^
| +-------- passing a 64-bit pointer 0x00000000.00000001
|
+---------------- treats the pointer argument as a 32-bit int and
happens to only see the all-zero 32-bits
I suspect that you'll get the output you expect if you change the printf() to:
printf("thread number : %d \n", (int) data);
As a general rule, when writing thread functions I think it's a good idea to have the first actions of the thread function be to convert the data item passed to the thread function to the type that was actually passed to pthread_create():
void* do_nothing(void* data)
{
int id = (int) data; // `pthread_create()` was passed an `int`
// `data` is not used again after this point
// ...
}
A few other points
if you pass an actual pointer to data to the thread function, make sure that each thread gets their own separate copy (unless the data is supposed to be the same instance for each thread, which is possible but uncommon).
if you're spinning up multiple threads you either need to keep each pthread_t object returned by pthread_create() (in an array, maybe) so you can join on them later, or you need to call pthread_join()/pthread_detach() before reusing the pthread_t object so that the system can clean up any resources it has allocated for that thread when the thread finished running. In the example as posted that might not matter much because the threads will run forever (or until something kills the process). The pthread_join() call you have will never complete successfully.
But the following code is destined to break when you change things so the thread function stops after some amount of time:
for (j = 0; j < NB_THREAD; j++)
{
pthread_join(thread, (void **) &res );
}
Because thread only has the pthread_t for the last thread created, once it successfully joins it's not valid to use any more. The next loop iteration will try to join a thread that's already been joined and is no longer valid.