Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading OpenMP在关键构造中支持死锁_Multithreading_Fortran_Openmp_Critical Section - Fatal编程技术网

Multithreading OpenMP在关键构造中支持死锁

Multithreading OpenMP在关键构造中支持死锁,multithreading,fortran,openmp,critical-section,Multithreading,Fortran,Openmp,Critical Section,我试图确切地理解为什么在并行区域中,关键构造嵌套在关键构造中时会发生死锁 我查阅了以下资料:作者写道: 在OpenMP中,如果在一个关键区域内调用一个函数,则会发生这种情况 包含另一个关键区域。在这种情况下,称为 函数将等待第一个关键区域终止-这将永远不会终止 发生 好吧,但为什么不呢?此外,来自:黑格、格奥尔格和格哈德·韦林。为科学家和工程师介绍高性能计算。华润出版社,2010年,第页。149: 当线程在临界区域内遇到临界指令时,它将永远阻塞 同样的问题,为什么 最后是查普曼、芭芭拉、加布里埃

我试图确切地理解为什么在并行区域中,关键构造嵌套在关键构造中时会发生死锁

我查阅了以下资料:作者写道:

在OpenMP中,如果在一个关键区域内调用一个函数,则会发生这种情况 包含另一个关键区域。在这种情况下,称为 函数将等待第一个关键区域终止-这将永远不会终止 发生

好吧,但为什么不呢?此外,来自:黑格、格奥尔格和格哈德·韦林。为科学家和工程师介绍高性能计算。华润出版社,2010年,第页。149:

当线程在临界区域内遇到临界指令时,它将永远阻塞

同样的问题,为什么

最后是查普曼、芭芭拉、加布里埃尔·乔斯特和路德·范德帕斯。使用OpenMP:便携式共享内存并行编程。第10卷。麻省理工学院出版社,2008年也提供了一个使用锁的例子,但是没有使用关键构造

根据我目前的理解,在嵌套的关键区域中发生死锁有两种不同的可能方式:

开始第一步:

如果两个线程到达一个嵌套的关键构造(一个关键区域在另一个关键区域内),线程一进入“外部”关键区域,线程二等待。引用查普曼等人的话

当一个线程遇到一个关键构造时,它会等待,直到没有其他线程出现 使用相同的名称执行关键区域

好的,到目前为止还不错。现在,线程1没有进入嵌套的关键区域,因为它是一个同步点,线程在这里等待所有其他线程到达,然后再继续。由于第二个线程正在等待第一个线程退出“外部”关键区域,因此它们处于死锁状态

先结束再开始

开始第二次拍摄:

两个线程都到达“外部”关键构造。线程1进入“外部”关键构造,线程2等待。现在,线程1进入“内部”关键构造并在其隐含的屏障处停止,因为它等待线程2。另一方面,线程2等待线程1退出到“外部”线程,因此两个线程都在永远等待

第二步结束

下面是一个生成死锁的小Fortran代码:

  1   subroutine foo
  2 
  3     !$OMP PARALLEL 
  4     !$OMP CRITICAL 
  5       print*, 'Hallo i am just a single thread and I like it that way'
  6     !$OMP END CRITICAL
  7     !$OMP END PARALLEL 
  8 
  9   end subroutine foo
 10 
 11 program deadlock
 12   implicit none
 13   integer :: i,sum = 0
 14 
 15   !$OMP PARALLEL
 16   !$OMP DO 
 17   do i = 1, 100
 18   !$OMP CRITICAL
 19      sum = sum + i
 20      call foo()
 21   !$OMP END CRITICAL
 22   enddo
 23   !$OMP END DO
 24   !$OMP END PARALLEL
 25 
 26   print*, sum
 27 end program deadlock
所以我的问题是,这两个建议中的一个是正确的,还是有其他的可能性
为什么在这种情况下会发生死锁。

没有隐含的障碍,即没有与关键构造关联的“线程等待其他线程到达的同步点”。相反,在关键构造开始时,线程会等待已在同名关键构造中的任何线程离开该构造

不能嵌套具有相同名称的关键构造,因为当前的OPEMP规则规定它们不能嵌套(请参阅OPEMP 4.0第2.16节中的嵌套限制)。这就是你问题的答案,也是讨论的结束——如果你违反了禁令,那么一切都可能发生

实际上,这种禁止允许实现假定具有相同名称的关键构造不会嵌套。一种常见的实现选择是,遇到关键构造的线程将等待所有线程(包括自身)离开该构造。如果正在等待,线程将无法离开。这导致了僵局

可以嵌套具有不同名称的关键构件。在这种情况下,如果嵌套不一致,则可能出现死锁。考虑:

!$OMP PARALLEL

!$OMP CRITICAL (A)
!$OMP CRITICAL (B)      ! Thread one waiting here.
!...
!$OMP OMP CRITICAL (B)
!$OMP END CRITICAL (A)

!$OMP CRITICAL (B)
!$OMP CRITICAL (A)      ! Thread two waiting here.
!...
!$OMP OMP CRITICAL (A)
!$OMP END CRITICAL (B)

!$END PARALLEL

如果出现这种情况,线程将等待相当长的时间。

对于您的解释,有一个小的后续问题:因此,当线程1进入“外部”临界区域时,线程2将在外部等待。现在线程1正在等待“任何”线程离开“内部”临界区域,这不会发生,因为一次只有一个线程可以进入“外部”临界区域。因此,它正在等待自己离开。这是正确的解释吗?为了正确起见,我将一个与你的后续行动相关的单词“any”改为“all”。一个合理的实现是,当它击中内部关键构造时,线程一(原子地)查询关键部分是否有线程在其中。答案是肯定的,因此线程等待。(如果答案是否,线程将(原子地与查询一起)标记关键部分已被占用并继续进入该部分。)线程结束等待自己。线程2是不相关的-它可能正在外部构造边界等待,或者正在飞往月球。谢谢你的评论。