mirx
mirx

Reputation: 626

Understanding threads in C

I have a math function in C which computes lots of complicated math. The function has a header:

double doTheMath(struct example *e, const unsigned int a,
                 const unsigned int b, const unsigned int c)
{
    /* ... lots of math */
}

I would like to call this function 100 times at the same time. I read about pthreads and think it could be a good solution for what I want to achieve. My idea is as follows:

pthread_t tid[100];
pthread_mutex_t lock;

if (pthread_mutex_init(&lock, NULL) != 0)
    {
        printf("\n mutex init failed\n");
        return 1;
    }

for(i=0; i<100; i++) {
    pthread_create(&(tid[i]), NULL, &doTheMath, NULL);
    pthread_mutex_lock(&lock);
    d += doTheMath(args);
    pthread_mutex_unlock(&lock); 
}

pthread_mutex_destroy(&lock);

My questions:

  1. How to pass to the doTheMath all the arguments it needs?
  2. Is there here really a point in using threads, will this even work as I want it to? I cant really understand it, when I lock my function call with the mutex, it won't let to call my function 100 times at the same time, right? So how can I do this?

EDIT:

So, summing up:

My function encrypts/decrypts some data using math - so I guess the order matters

When I do it like this:

pthread_t tid[100];
for(i=0; i<100; i++)
     pthread_create(&(tid[i]), NULL, &doTheMath, NULL);

it will create my 100 threads (my machine is capable of running, for sure) and I dont need a mutex, so it will call my function 100 times at the same time?

How about cPU cores? When I do it like this, will all of my CPU cores be fully loaded?

Having just one, single function call will load only one core of my CPU, having 100 (or more) threads created and running and calling my function will load all my CPU cores - am I right here?

Upvotes: 1

Views: 153

Answers (2)

Crozin
Crozin

Reputation: 44396

How to pass to the doTheMath all the arguments it needs?

You'll have to create a proxy function that has a signature acceptable by pthread_create, which invokes the actual functions in its body:

struct doTheMathArgs {
    struct example *e;
    const unsigned int a, b, c;
};

callDoTheMath(void *data) {
    struct doTheMathArgs *args = data;

    doTheMath(args->e, args->a, args->b, args->c);
}

...

struct doTheMathArgs dtma;
dtma.e = ...;
...
dtma.c = ...;

pthread_create(&(tid[i]), NULL, &callDoTheMath, (void *) &dtma);

Is there here really a point in using threads, will this even work as I want it to? I cant really understand it, when I lock my function call with the mutex, it wont let to call my function 100 times at the same time, right? So how can I do this?

Unless you're working on a computer that is really capable of running 100 threads at a time your code is going to slow down the entire process. You should rather stay with a number of threads that's your maschine is capable of running.

To answer the futher part of your question you'll have to tell us how your doTheMath function works. Is each invocation of this function completley independant from others? Does the order of invocations matter?

Upvotes: 2

abligh
abligh

Reputation: 25179

Yes, you can do this with threads. Whether calling it 100 times actually speeds things up is a separate question, as once all your CPU cores are fully loaded, trying to run more things at once is likely to decrease speed rather than increase it as processor cache efficiency is lost. For CPU intensive tasks the optimum number of threads is likely to be the number of CPU cores (or a few more).

As to your specific questions:

Q1: When you use phtread_create the last parameter is void *arg, which is an opaque pointer passed to your thread. You would normally use that as a pointer to a struct containing the parameters you want to pass. This might also be used to return the calculated sum. Note that you will have to wrap do_the_maths in a suitable second function so its signature (return value and parameters) look like that expected by pthread_create.

Q2. See above for general warning re too many threads, but uses this a useful technique.

Specifically:

  • You do not want to use a mutex in the way you are doing. A mutex is only needed to protect parts of your code which are accessing common data (critical sections).

  • You both create a thread to call doTheMath, then also call doTheMath directly from the main thread. This is incorrect. You should instead merely create all the threads (in one loop), then run another loop to wait for each of the threads to complete, and sum the returned answers.

Upvotes: 2

Related Questions