OpenMP了解关键构造中的死锁

时间:2014-11-26 16:37:09

标签: multithreading fortran openmp critical-section

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

我咨询了以下资源:作者撰写的this来源:

  

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

好吧,但为什么不呢?此外来自:Hager,Georg和Gerhard Wellein。为科学家和工程师介绍高性能计算。 CRC Press,2010,p。 149:

  

当线程在关键区域内遇到CRITICAL指令时,它将永远阻塞。

同样的问题,为什么?

最后,Chapman,Barbara,Gabriele Jost和Ruud Van Der Pas。使用OpenMP:可移植共享内存并行编程。卷。 10.麻省理工学院出版社,2008年也提供了一个使用锁的例子,但没有使用关键结构。

根据我目前的理解,嵌套关键区域中出现死锁的方法有两种:

首先开始:

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

  

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

好吧,到目前为止一切顺利。现在,第一个线程不会进入嵌套的关键区域,因为它是一个同步点,线程在继续之前等待所有其他线程到达。并且由于第二个线程正在等待第一个线程退出“外部”关键区域,因此它们处于死锁状态。

结束先拍摄。

开始第二次拍摄:

两个线程都到达“外部”关键构造。线程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

所以我的问题是,这两个建议中的一个是正确的,还是有另一种可能性 为什么在这种情况下发生僵局。

1 个答案:

答案 0 :(得分:4)

没有隐含的障碍,即没有"同步点,其中线程等待其他线程到达"与CRITICAL结构相关联。相反,在关键构造的开头,线程等待已经在中的任何线程一个同名的关键构造离开构造。

关键构造具有相同的名称​​不能嵌套,因为当前的OpemMP规则说它们不能(参见OpemMP 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

如果出现这种情况,线程将会等待很长时间。