【问题标题】:Avoding multiple thread spawns in pthreads避免在 pthread 中产生多个线程
【发布时间】:2010-05-24 10:33:39
【问题描述】:

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

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

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

编辑:

我只是给出了代码的简化版本。

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 并测试是否已经创建?

【问题讨论】:

  • 第二个马塞洛。没有足够的信息来理解问题。代码可能完全按照您的要求执行(生成线程)。我们需要查看您的代码的简化版本。在你这样做之前:你是否在创建线程时保存它,然后在生成另一个线程之前测试线程是否已经创建?
  • 我只是给出了代码的简化版本。 int main() { //一些代码做 { compute_distance(objects,clusters, &delta); // 带有 pthread 的例程 } while (delta > threshold ) void compute_distance(double *objects,double *clusters, double *delta) { //一些代码再次 //计算移动到一个单独的并行例程.. for (i =0, i)&ip); for (i=0, i

标签: c++ c pthreads


【解决方案1】:

您可以创建一个简单的线程池实现来创建线程并让它们休眠。一旦需要一个线程,而不是“pthread_create”,您可以要求线程池子系统获取一个线程并执行所需的工作。这将确保您对线程数量的控制..

【讨论】:

  • 嗨.. 感谢您的回复。问题是我使用基准套件中的基准,我不想对原始源代码进行大量更改。这是正确的方法,但我想知道是否有解决方法来避免对源代码进行大量更改。
【解决方案2】:

您可以通过最少的代码更改来做一件简单的事情,即为 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 初始化为零。

不过,弄乱这些挥发物可能会很麻烦。您可能需要花一些时间才能让我的粗略大纲真正正常工作。

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 2010-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-23
      相关资源
      最近更新 更多