首页 > 解决方案 > OpenMP 任务循环:两个连续任务循环结构之间的同步

问题描述

两个taskloop构造之间的同步是如何完成的?具体来说,在下面的伪代码中,如果可用线程数多于第一个循环的任务数,我相信这些空闲线程会在单个构造末尾的隐式屏障处旋转。现在是否允许这些空闲线程同时开始执行第二个循环,使得以这种方式并行化事物是不安全的(由于对数组的相互依赖A)?

!$omp parallel
!$omp single

!$omp taskloop num_tasks(10)
DO i=1, 10
    A(i) = foo()
END DO
!$omp end taskloop

!do other stuff

!$omp taskloop
DO j=1, 10
    B(j) = A(j)
END DO
!$omp end taskloop

!$omp end single
!$omp end parallel

我无法从 API 规范中找到明确的答案:https ://www.openmp.org/spec-html/5.0/openmpsu47.html#x71-2080002.10.2

标签: parallel-processingsynchronizationtaskopenmpshared-memory

解决方案


默认情况下,该taskloop构造有一个隐含的taskgroup围绕它。考虑到这一点,您的代码会发生什么是single构造从并行团队的可用线程中挑选任何一个线程(我将其称为生产者线程)。然后将 n-1 个其他线程直接发送到single构造的屏障并等待工作到达(任务)。

现在发生的taskgroup情况是生产者线程开始创建循环任务,然后在taskloop构造结束时等待所有创建的任务完成:

!$omp parallel
!$omp single

!$omp taskloop num_tasks(10)
DO i=1, 10
    A(i) = foo()
END DO
!$omp end taskloop  ! producer waits here for all loop tasks to finish

!do other stuff

!$omp taskloop
DO j=1, 10
    B(j) = A(j)
END DO
!$omp end taskloop ! producer waits here for all loop tasks to finish

!$omp end single
!$omp end parallel

因此,如果您的并行度(= first 创建的任务数taskloop)少于屏障中的 n-1 个工作线程,那么其中一些线程将空闲。

如果你想要更多的重叠并且如果“其他东西”独立于第一个taskloop,那么你可以这样做:

!$omp parallel
!$omp single


!$omp taskgroup
!$omp taskloop num_tasks(10) nogroup
DO i=1, 10
    A(i) = foo()
END DO
!$omp end taskloop  ! producer will not wait for the loop tasks to complete

!do other stuff

!$omp end taskgroup ! wait for the loop tasks (and their descendant tasks)

!$omp taskloop
DO j=1, 10
    B(j) = A(j)
END DO
!$omp end taskloop

!$omp end single
!$omp end parallel

唉,从 5.1 版开始的 OpenMP API 不支持 taskloop 构造的任务依赖性,因此您无法轻松描述 firsttaskloop和 second的循环迭代之间的依赖性taskloop。OpenMP 语言委员会目前正在研究此问题,但我认为这不是针对 OpenMP API 5.2 版实现的,而是针对 6.0 版实现的。

PS(编辑):对于第二个taskloop,因为它就在single构造结束之前,因此就在障碍之前,您也可以轻松地添加nogroup那里以避免额外的等待生产者线程。


推荐阅读