两个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
最佳答案
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
因此,如果您的并行度(= 第一个 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
的循环迭代之间的依赖关系。第二个taskloop
。 OpenMP 语言委员会目前正在研究此问题,但我认为这不是针对 OpenMP API 版本 5.2 实现的,而是针对版本 6.0 实现的。
PS(编辑):第二个taskloop
因为它就在 single
结束之前构造,因此在障碍之前,您可以轻松添加 nogroup
也可以避免额外等待生产者线程。
关于parallel-processing - OpenMP 任务循环 : synchronization between two consecutive taskloop constructs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66455187/