使用pthreads并行化多个核心上的数据处理

时间:2017-03-31 05:18:56

标签: linux multithreading pthreads worker

我的目标是使用多个工作线程处理多个核心上的数据,然后在主线程中进一步处理结果。我在linux上工作,我想使用pthreads。我创建了一个简单的例子来学习如何正确地做到这一点。我有一个主线程名为"回调"和4个工人线程。这个想法是主线程通知工作线程开始处理,然后4个线程在主线程完成时发出信号,主线程在所有4个线程通知它们完成后退出。我希望4个工作线程能够并行运行,所以我不希望任何这些线程等待其他线程。在我的例子中,我试图让每个线程休眠不同的持续时间(1,2,3和4秒),并认为代码将在4秒后退出(即当工作线程4有完成等待4秒)。

出于某种原因,我的代码不正确,并且它总是立即退出,打印出来:

thread 3 start (sleeping 3000 ms)
thread 2 start (sleeping 2000 ms)
thread 1 start (sleeping 1000 ms)
thread 4 start (sleeping 4000 ms)
    thread 1 stop
    thread 2 stop
    thread 3 stop
    thread 4 stop
Main(): Waited on 5  threads. Done.

所以线程确实似乎以正确的顺序退出,但程序运行不需要4秒。

这里发生了什么?我已粘贴下面的代码

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

// based on https://computing.llnl.gov/tutorials/pthreads/#ConditionVariables

#define DUR 1000
#define NUM_THREADS 5
int state = 0; 

pthread_mutex_t mutex;
pthread_cond_t conddone;
pthread_cond_t condwork;

void* callback(void* t) { 

    // signal worker threads to start work 

        pthread_mutex_lock(&mutex);
        pthread_cond_broadcast(&condwork);
        pthread_mutex_unlock(&mutex);

    // wait for worker threads to finish 

        pthread_mutex_lock(&mutex);
        while (state < 4)
            pthread_cond_wait(&conddone, &mutex);
        pthread_mutex_unlock(&mutex);

   pthread_exit(NULL);

} 

void* worker(void* t) { 

   long id = (long)t;

    // wait for signal from callback to start doing work 

    pthread_mutex_lock(&mutex);
    pthread_cond_wait(&condwork, &mutex);
    pthread_mutex_unlock(&mutex);

    // do work 

    printf("thread %d start (sleeping %d ms)\n", id, id * DUR); 
    usleep(id * DUR); 
    printf("    thread %d stop\n", id); 

    // tell callback we're done 

    pthread_mutex_lock(&mutex);
    state++;
    pthread_cond_signal(&conddone);
    pthread_mutex_unlock(&mutex);

   pthread_exit(NULL);

}


int main (int argc, char *argv[])
{
   int i, rc;

   pthread_t threads[5];
   pthread_attr_t attr;

   pthread_mutex_init(&mutex, NULL);
   pthread_cond_init (&condwork, NULL);
   pthread_cond_init (&conddone, NULL);

   pthread_attr_init(&attr);
   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

   pthread_create(&threads[0], &attr, callback, (void *)0);
   pthread_create(&threads[1], &attr, worker, (void *)1);
   pthread_create(&threads[2], &attr, worker, (void *)2);
   pthread_create(&threads[3], &attr, worker, (void *)3);
   pthread_create(&threads[4], &attr, worker, (void *)4);

   for (i=0; i<NUM_THREADS; i++) {
     pthread_join(threads[i], NULL);
   }
   printf ("Main(): Waited on %d  threads. Done.\n", NUM_THREADS);

   pthread_attr_destroy(&attr);
   pthread_mutex_destroy(&mutex);
   pthread_cond_destroy(&condwork);
   pthread_cond_destroy(&conddone);
   pthread_exit(NULL);
} 

1 个答案:

答案 0 :(得分:1)

您的直接问题只是usleep()睡眠微秒而不是毫秒,因此您的线程正在睡眠的时间是您打算的千分之一。

但是,您确实遇到了另一个问题:您的condwork条件变量未与共享状态的谓词配对(例如state < 4变量的谓词conddone。如果其中一个工作线程在“回调”线程执行pthread_cond_wait()后执行pthread_cond_broadcast(),则工作人员将无限期地等待。

您可以通过将state变量初始化为-1来解决此问题:

int state = -1;

让你的员工等待谓词state < 0

// wait for signal from callback to start doing work 

pthread_mutex_lock(&mutex);
while (state < 0)
    pthread_cond_wait(&condwork, &mutex);
pthread_mutex_unlock(&mutex);

并通过将状态设置为0来使“回调”向工作人员发出信号:

// signal worker threads to start work 

pthread_mutex_lock(&mutex);
state = 0;
pthread_cond_broadcast(&condwork);
pthread_mutex_unlock(&mutex);