"omp single" 和 "omp task" 如何提供并行性?

7

我对omp singleomp task指令感到困惑。我读过几个使用两者的示例。以下示例展示如何使用任务构造处理链接列表的元素。

1  #pragma omp parallel
2  {
3      #pragma omp single
4      {
5          for(node* p = head; p; p = p->next)
6          {
7              #pragma omp task
8              process(p); 
9          }
10     }
11 }

我不理解这个例子中的并行性。使用omp single,只有一个线程会执行与single构造相关的结构化块,是这样吗?在此示例中,第4-10行是与single构造相关的结构化块,它只能执行一次,那么为什么我们可以在此结构化块内使用omp task?它怎么能以并行方式工作?

3个回答

17

除了其他答案之外,让我深入挖掘一下执行过程中发生的情况。

1  #pragma omp parallel
2  {
3      #pragma omp single
4      {
5          for(node* p = head; p; p = p->next)
6          {
7              #pragma omp task
8              process(p);
9          }
10     } // barrier of single construct
11 }
在代码中,我在single结构结束时引入了一个屏障。具体操作如下:首先,当遇到parallel结构时,主线程会生成并行区域并创建一组工作线程。然后你有n个线程在运行和执行并行区域。其次,single结构选择任意一个n个线程并执行single结构花括号内的代码。其他n-1个线程将继续前进到第10行的屏障。在那里,它们将等待最后一个线程赶上并完成障碍同步。当这些线程在那里等待时,它们不仅浪费时间,而且等待着工作到达。第三,由single结构选择的线程(“生产者”)执行for循环,并针对每个迭代创建一个新任务。然后将此任务放入任务池中,以便另一个线程(屏障中的线程之一)可以接收并执行它。生产者完成创建任务后,将加入屏障,如果任务池中仍有等待执行的任务,则它将帮助其他线程执行任务。第四,在生成和执行所有任务之后,所有线程都已完成,障碍同步已完成。虽然OpenMP实现如何执行任务还有更多细节,但从概念上讲,以上是您可以考虑的操作,直到您准备深入了解OpenMP API中任务调度的特定方面为止。

2
#pragma omp task可以在单个线程上进行调度,但是它可以被其他线程执行。这是使用OpenMP任务的一个目的:提供并行性的线程不一定是并行计算的执行者。
请注意,任务在调度点执行。 omp parallel部分的结束是一个调度点。这就是为什么所有其他OpenMP线程都应该执行已调度的任务(只要任务足够长)。

2

所以我们将逐步进行:

  1. 当您编写语句 #pragma omp parallel 时,会创建一个线程组成的并行区域。

  2. 然后您编写了 #pragma omp single,单个线程会创建任务,并将它们添加到属于该团队的队列中。

  3. 最后,您编写了 #pragma omp task。执行此代码段的线程将创建一个任务,稍后可能由不同的线程执行,并将其添加到属于该团队的队列中,以及该团队中的所有线程(可能包括生成任务的线程)。任务的执行时间由任务调度程序决定,对用户不可见。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接