我正在努力理解为什么在并行区域中嵌套关键构造时会发生死锁。
我查阅了以下资源:这个来源,作者写道:
在OpenMP中,如果在关键区域内调用包含另一个关键区域的函数,则可能会发生这种情况。在这种情况下,被调用函数的关键区域将等待第一个关键区域终止-而这永远不会发生。
好的,但为什么呢?此外,来自Hager、Georg和Gerhard Wellein的《Introduction to high performance computing for scientists and engineers》(CRC Press,2010)第149页:
当线程在关键指令内部遇到CRITICAL指令时,它将永远阻塞。
同样的问题,为什么呢?
最后,Chapman、Barbara、Gabriele Jost和Ruud Van Der Pas的《Using OpenMP: portable shared memory parallel programming》(Vol. 10,MIT press,2008)也提供了一个使用锁的示例,但没有使用关键构造。
根据我目前的理解,在嵌套的关键区域中发生死锁有两种不同的可能方式:
第一种情况:
如果两个线程到达嵌套的关键构造(一个关键区域内部另一个关键区域),线程一进入“外部”关键区域,线程二等待。引用Chapman等人的话:
当线程遇到关键构造时,它会等待,直到没有其他线程正在执行具有相同名称的关键区域。
好的,到目前为止都很好。现在,线程一不进入嵌套的关键区域,因为它是一个同步点,在此处线程等待所有其他线程到达后再继续执行。由于第二个线程正在等待第一个线程退出“外部”关键区域,所以它们处于死锁状态。
第二种情况:
两个线程都到达了“外部”关键结构。线程一进入“外部”关键结构,线程二等待。现在,线程一进入“内部”关键结构并停在其隐含的屏障上,因为它正在等待线程二。另一方面,线程二在等待线程一退出“外部”线程,因此两个线程都将永久等待。
以下是产生死锁的小型Fortran代码:
所以我的问题是,这两个建议中是否有一个是正确的,或者在这种情况下死锁发生的原因是否还有其他可能性。
我查阅了以下资源:这个来源,作者写道:
在OpenMP中,如果在关键区域内调用包含另一个关键区域的函数,则可能会发生这种情况。在这种情况下,被调用函数的关键区域将等待第一个关键区域终止-而这永远不会发生。
好的,但为什么呢?此外,来自Hager、Georg和Gerhard Wellein的《Introduction to high performance computing for scientists and engineers》(CRC Press,2010)第149页:
当线程在关键指令内部遇到CRITICAL指令时,它将永远阻塞。
同样的问题,为什么呢?
最后,Chapman、Barbara、Gabriele Jost和Ruud Van Der Pas的《Using OpenMP: portable shared memory parallel programming》(Vol. 10,MIT press,2008)也提供了一个使用锁的示例,但没有使用关键构造。
根据我目前的理解,在嵌套的关键区域中发生死锁有两种不同的可能方式:
第一种情况:
如果两个线程到达嵌套的关键构造(一个关键区域内部另一个关键区域),线程一进入“外部”关键区域,线程二等待。引用Chapman等人的话:
当线程遇到关键构造时,它会等待,直到没有其他线程正在执行具有相同名称的关键区域。
好的,到目前为止都很好。现在,线程一不进入嵌套的关键区域,因为它是一个同步点,在此处线程等待所有其他线程到达后再继续执行。由于第二个线程正在等待第一个线程退出“外部”关键区域,所以它们处于死锁状态。
第二种情况:
两个线程都到达了“外部”关键结构。线程一进入“外部”关键结构,线程二等待。现在,线程一进入“内部”关键结构并停在其隐含的屏障上,因为它正在等待线程二。另一方面,线程二在等待线程一退出“外部”线程,因此两个线程都将永久等待。
以下是产生死锁的小型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
所以我的问题是,这两个建议中是否有一个是正确的,或者在这种情况下死锁发生的原因是否还有其他可能性。