2

我是英特尔 TBB 的新手。我正在使用 concurrent_queue 以在我的项目中实现细粒度的并行性。我有几个疑问。这就是我正在实施的方式。

   thread_fun(arguments) {
      while(concurrent_queue.try_pop(v))
          operation on v;  //each thread executes its own operation(seperate v for each thread)
   }
   main() {
      for(..)
         concurrent_queue.push(); //fill the queue
      _beginthreadex(..); //create 8 win32 threads and pass concurrent_queue as an argument
   }
  1. 我明确提到了线程数。我读到 TBB 将根据处理器核心数创建线程。我怎样才能做到这一点?这样我就不需要使用 _beginthreadex 函数显式创建线程了吗?

  2. 我是否通过使用 concurrent_queue 来实现细粒度的并行性?

  3. 任务级并行性是什么意思?您如何使用 intel tbb 实现任务级并行性?我正在从队列中弹出元素。弹出操作是否被视为一项任务?这意味着,所有弹出操作都被视为不同的任务。我一次用 8 个线程弹出 8 个元素。这意味着,我正在实现任务级别的并行性。我对么?

  4. 如果我将四核处理器上的线程数增加到 32(支持 8 个线程),concurrent_queue 是如何工作的?队列上只有8个线程并发执行还是总共32个线程并发执行?

请帮我。

4

1 回答 1

5

TBB 有很多部分。Concurrent_queue 只是一个可以被多个线程安全访问的队列。并发队列不直接属于 TBB 的“细粒度并行”或“任务并行”部分。(虽然这些部分可以使用concurrent_queue。)

  1. 您可以使用tbb::parallel_for. 请参阅该页面上的示例或此堆栈溢出问题。当您使用 parallel_for 时,tbb 将负责所有线程的创建,并且还将进行动态负载平衡。

  2. Concurrent_queue 根本不创建任何并行性:它只是允许多个线程安全(并且相对有效地)访问同一个队列。它确保没有竞争条件。在您的示例中,您获得的并发线程数不超过 8 个。实际上:concurrent_queue 正在序列化对队列的访问。您的并行性来自您的“对 v 的操作”。对 concurrent_queue 的访问应该被认为是开销。

  3. 您在示例中实现了一种基本的任务级并行性。我从@Mitch Wheat 的 Stack Overflow 答案中找到了对任务和线程之间区别的精彩描述

    任务是你想做的事情。

    线程可能是执行该任务的许多工作人员之一。

    从技术上讲:任务不能相互阻塞等待。您的任务是您正在执行的“对 v 的操作”。您正在实现任务级并行性。使用类似的东西的优点tbb::parallel_for是它(a)自动为您启动线程,(b)尝试自动选择最适合您用户系统上的内核数量的线程数,(c)经过优化以减少将任务分配给线程的开销,并且 (d) 如果您的任务操作长度不相等,也可以进行一些非常酷的动态负载平衡。

  4. 让我们区分并发并行。你的机器有 8 个硬件线程。因此,您的最大 cpu 并行度为 8。我会使用术语并发来表示“如果您拥有一个具有无限数量内核的神奇处理器,您可以实现的最大并行度”。通常,创建的线程数多于内核数的主要原因是您的线程正在执行大量长延迟 i/o 操作。操作系统可以切换到一个额外的线程来做 cpu 工作,而另一个线程正在等待磁盘/网络。

于 2013-04-07T02:33:14.600 回答