【问题标题】:Wait for threads in threadpool between loop iterations在循环迭代之间等待线程池中的线程
【发布时间】:2013-01-23 03:46:52
【问题描述】:

我有几个程序在做大量的计算,由于我的新计算机有一个多核处理器,我决定重写我的多线程程序。我找到了 Johan Hanssen Seferidis 的 thpool library 并正在尝试使用它。

我有一个小循环(比如0 < j < 12)嵌入到一个更大的循环(0 < i < 40000)中。对于i 的每次迭代,小的 j 循环将其工作分配给线程池。每个 j 有一份工作。线程出现并抓住任何尚未被采取的东西。我需要一种方法让大型 i-loop 等到所有线程都完成了 j-loop 中的工作,以及任何 I/O 操作,然后继续 i++。

简单示例代码:

#include <stdio.h>
#include "thpool.h"

int i;

void task1(int a){
printf("# Thread working: %u\n", (int)pthread_self());
printf(" Task 1 running..\n");
printf("%d\n", 10*i+a);
}

int main(){
int j;

#define NUM_HANDLER_THREADS 3

thpool_t* threadpool;
threadpool=thpool_init(NUM_HANDLER_THREADS);

for (i=0; i<5; i++)
  for (j=0; j<10; j++) {
    thpool_add_work(threadpool, (void*)task1, (void*)j);
    };

sleep(2);
puts("Will kill threadpool");
thpool_destroy(threadpool);

return 0;
}

编译:

gcc main.c thpool.c -pthread -o test

执行上面应该(即我想要的)按顺序写五个块0-9、10-19、...、40-49,但是每个块的元素可能或多或少是随机顺序.相反,程序通过整个 i 循环太快了,所以当线程开始写入 i==5 时,我得到 50-59 五次,以随机顺序。

我希望我清楚自己想要做什么。也许是这样的:

for (i=0; i<5; i++) {
  for (j=0; j<10; j++) {
  thpool_add_work(threadpool, (void*)task1, (void*)j);
  wait_for_all_threads_to_finish();
  }
};

有什么想法吗?加入?退出?信号量?这对我来说是全新的,所以感谢您的耐心等待。

【问题讨论】:

  • 您只是在进行数据竞赛。多个线程无锁访问同一个变量i。与其添加同步,不如不要访问它。通过函数参数将所有需要的信息传递给工作人员。
  • 如果你希望你的工作在 N 个块中完成,而不是在一个连续的流中,你确实需要同步。但尚不清楚为什么需要这样的块。
  • 嗨,我是制作 C-Thread-Pool 库的人。截至 2015 年 1 月,函数 thpool_wait() 可以完全满足您的需求。请注意,API 略有变化(变得更好)。

标签: c loops gcc threadpool wait


【解决方案1】:

我建议使用这样的信号量:

    #include <stdio.h>
    #include <semaphore.h>
    #include "thpool.h"

    int i;
    sem_t sem;

    void
    task1(int a)
    {
      sem_post(&sem);
      printf("# Thread working: %u\n", (int)pthread_self());
      printf(" Task 1 running..\n");
      printf("%d\n", 10*i+a);
    }

    int
    main(void)
    {
      int j;

      if (sem_init(&sem, 0, 0) == -1)
        abort();

      #define NUM_HANDLER_THREADS 3

      thpool_t* threadpool;
      threadpool=thpool_init(NUM_HANDLER_THREADS);

      for (i=0; i<5; i++)
        {
          for (j=0; j<10; j++)
            {
              thpool_add_work(threadpool, (void*)task1, (void*)j);
              sem_wait(&sem);
            }
        }

      sleep(2);
      puts("Will kill threadpool");
      thpool_destroy(threadpool);

      return 0;
    }

也可以尝试:

    void
    task1(int a)
    {
      printf("# Thread working: %u\n", (int)pthread_self());
      printf(" Task 1 running..\n");
      printf("%d\n", 10*i+a);
      sem_post(&sem);
    }

看看区别。祝你好运。

【讨论】:

  • 我尝试了你的建议,但它并没有达到我想要的效果。通过将sem_wait(&amp;sem); inside 放在 j 循环中,一切都被执行,就好像我什至没有使用多线程一样:直到下一次 j 递增时才会发生任何事情。我需要的是这样的:对于i 的每个新值,j 循环旋转并将工作发送到线程池。每个j 完成的顺序并不重要,重要的是所有 ji 可以递增之前完成计算。我尝试将sem_wait(&amp;sem); 移到 j-loop 之外,但仍在 i-loop 内,但不行:(
猜你喜欢
  • 2021-01-04
  • 1970-01-01
  • 2018-07-24
  • 1970-01-01
  • 1970-01-01
  • 2015-07-13
  • 2015-08-29
  • 2010-10-16
相关资源
最近更新 更多