避免在pthreads中产生多个线程

时间:2010-05-24 10:33:39

标签: c++ c pthreads

我有一个使用pthreads并行化的应用程序。应用程序具有迭代例程调用和在rountine(pthread_create和pthread_join)中生成的线程,以并行化例程中的计算密集部分。当我使用像PIN这样的工具来收集统计数据时,工具会报告多个线程的统计信息(没有线程x没有迭代)。我相信它是因为它在每次调用例程时产生新的线程集。

  1. 如何确保我只创建一次线程,并且所有后续调用都使用先创建的线程。

  2. 当我对OpenMP执行相同操作然后尝试收集统计信息时,我发现线程只创建一次。是否是OpenMP运行时?

  3. 修改

    im jus给出了代码的简化版本。

    int main() 
    { 
      //some code 
      do { 
        compute_distance(objects,clusters, &delta); //routine with pthread 
      } while (delta > threshold ) 
    }
    void compute_distance(double **objects,double *clusters, double *delta) 
    { 
       //some code again 
       //computation moved to a separate parallel routine.. 
       for (i=0, i<nthreads;i++) 
         pthread_create(&thread[i],&attr,parallel_compute_phase,(void*)&ip); 
       for (i=0, i<nthreads;i++) 
         rc = pthread_join(thread[i], &status); 
    } 
    

    我希望这清楚地解释了这个问题。

    1. 我们如何保存线程ID并测试是否已创建?

3 个答案:

答案 0 :(得分:0)

您可以创建一个简单的线程池实现,它可以创建线程并让它们进入休眠状态。一旦需要一个线程,而不是“pthread_create”,你可以要求线程池子系统拿起一个线程并完成所需的工作。这将确保你控制线程数。

答案 1 :(得分:0)

使用最少的代码更改可以轻松完成的事情是为pthread_create和_join编写一些包装器。基本上你可以这样做:

typedef struct {
  volatile int go;
  volatile int done;
  pthread_t h;
  void* (*fn)(void*);
  void* args;
} pthread_w_t;

void* pthread_w_fn(void* args) {
    pthread_w_t* p = (pthread_w_t*)args;
    // just let the thread be killed at the end
    for(;;) {
        while (!p->go) { pthread_yield(); };  // yields are good
        p->go = 0;  // don't want to go again until told to
        p->fn(p->args);
        p->done = 1;
    }
}

int pthread_create_w(pthread_w_t* th, pthread_attr_t* a,
                     void* (*fn)(void*), void* args) {
    if (!th->h) {
        th->done = 0;
        th->go = 0;
        th->fn = fn;
        th->args = args;
        pthread_create(&th->h,a,pthread_w_fn,th);
    }
    th->done = 0; //make sure join won't return too soon
    th->go = 1;   //and let the wrapper function start the real thread code
}

int pthread_join_w(pthread_w_t*th) {
  while (!th->done) { pthread_yield(); };
}

然后你将不得不改变你的调用和pthread_ts,或者创建一些#define宏来将pthread_create更改为pthread_create_w等....你必须将你的pthread_w_ts初始化为零。

然而,弄乱这些挥发物可能会很麻烦。你可能需要花一些时间让我的粗略轮廓真正正常工作。

答案 2 :(得分:0)

要确保多个线程可能尝试执行的操作只发生一次,请使用pthread_once()。要确保只有一个线程可以执行某些操作,只需使用bool(可能是静态存储中的一个)。

老实说,如果你想编辑你的问题,那么回答你的问题会容易得多 - 而不是评论,因为这会破坏格式化 - 包含有问题的真实代码,包括OpenMP编译指示。