我对omp single
和omp 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
,只有一个线程将执行与单个构造相关的结构化块,对吗?在这个例子中,第4-10行是与单个构造相关的结构化块,它只能执行一次,那么为什么我们可以在这个结构化块中使用omp task
呢?如何并行工作呢?
发布于 2021-07-23 17:32:04
在其他答案的基础上,让我更深入地研究执行过程中发生的事情。
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中深入研究任务调度的特定方面之前,您可以想到正在发生的事情。
发布于 2021-07-23 16:36:20
#pragma omp task
在单个线程上调度一个任务,但它可以由其他线程执行。这是使用OpenMP任务的目的之一:提供并行性的线程不一定是并行执行计算的线程。
注意,任务在调度点执行。omp parallel
部分的末尾是调度点。这就是为什么所有其他OpenMP线程都应该执行计划的任务(只要任务持续时间足够长)。
发布于 2021-07-23 16:52:01
因此,我们将一步一步地走:
当您编写语句#
然后,
。
https://stackoverflow.com/questions/68502197
复制相似问题