简体   繁体   中英

Why is the execution of 2 threads slower than that of 1 thread in C?

I am using the pthread library to make a program to find the accurate value of pi with Leibniz formula. I am working on shared resource here. My multithreaded function looks like this:

void *Leibniz(void *vars)
{
    struct variables *val = (struct variables *)vars;
    int startLimit = val->start;
    int endLimit = val->end;
    
    int i;
    for (i = startLimit; i <= endLimit; i++)
    {
        pthread_mutex_lock(&mutex);
        sum += (pow(-1, i) / ((2 * i) + 1));
        pthread_mutex_unlock(&mutex);
    }
}

When I run the program with N iterations and 1 thread, I get the correct output in about 4.5 seconds average. When I run the same program with two threads, it takes around 18 seconds. I have to use multithreading to make the program faster but the exact opposite is happening. Can anyone explain why?

You use locks to ensure that sum += (pow(-1, i) / ((2 * i) + 1)); is calculated in exactly one thread at a time. Multi threading can potentially be faster only when multiple threads do work at the same time.

Mutexes and thread creation itself are costly which is why the multi threaded non-parallel program is slower than single threaded one.

What is your proposed solution?

Don't have shared resources. In this case, have separate sum for each thread, then sum the sums in the end. Divide and conquer.

It looks like you aren't expressing what you thought.

Instead of locking on each loop iteration (which degrades performance due to many context switches), what you probably wanted is updating the sum at the end of calculation:

(note: only 1 lock needed when updating the shared sum):

{
    struct variables *val = (struct variables *)vars;
    int startLimit = val->start;
    int endLimit = val->end;

    // note: this part is calculated by each thread separatly
    // no (expensive) locking here

    double local_sum = 0;
    for (int i = startLimit; i <= endLimit; i++)
    {
         local_sum += (pow(-1, i) / ((2 * i) + 1));
    }

    // now update the sum (which is shared among all threads)
    // so need some kind of synchronization here
    // -> only 1 lock instead of (endLimit - startLimit + 1) times locking
    pthread_mutex_lock(&mutex);
    sum += local_sum;
    pthread_mutex_unlock(&mutex);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM