do-cycle-exit 中的 Coarray 死锁
Coarray deadlock in do-cycle-exit
下面的Coarray代码出现了一个奇怪的现象
program strange
implicit none
integer :: counter = 0
logical :: co_missionAccomplished[*]
co_missionAccomplished = .false.
sync all
do
if (this_image()==1) then
counter = counter+1
if (counter==2) co_missionAccomplished = .true.
sync images(*)
else
sync images(1)
end if
if (co_missionAccomplished[1]) exit
cycle
end do
write(*,*) "missionAccomplished on image ", this_image()
end program strange
这个程序永远不会结束,因为循环内任何超过 1 的计数器阈值似乎都存在死锁。该代码使用 Intel Fortran 2018 Windows OS 编译,具有以下标志:
ifort /debug /Qcoarray=shared /standard-semantics /traceback /gen-interfaces /check /fpe:0 normal.f90 -o run.exe
同样的代码,使用 DO WHILE 构造,也出现同样的现象:
program strange
implicit none
integer :: counter = 0
logical :: co_missionAccomplished[*]
co_missionAccomplished = .true.
sync all
do while(co_missionAccomplished[1])
if (this_image()==1) then
counter = counter+1
if (counter==2) co_missionAccomplished = .false.
sync images(*)
else
sync images(1)
end if
end do
write(*,*) "missionAccomplished on image ", this_image()
end program strange
这现在看起来太微不足道了,不可能成为编译器错误,所以我可能遗漏了一些关于并行 do 循环的重要信息。感谢您的帮助。
更新:
在上面的DO-CYCLE-EXIT 示例程序中的CYCLE 语句之前添加SYNC ALL 语句解决了死锁。此外,在 DO WHILE 语句之后的 SYNC ALL 语句作为块的第一行解决了死锁。显然,在上述任何一种情况下,所有图像都必须同步以避免在每个循环周期之前出现死锁。
关于"This seems now too trivial to be a compiler bug",您可能会惊讶于编译器如何错误地处理看似微不足道的事情。与 coarrays 相关的事情很少。
考虑以下相关程序:
implicit none
integer i[*]
do i=1,1
sync all
print '(I1)', i[1]
end do
end
我得到了最初令人惊讶的输出
1
2
当 运行 在 ifort 2018.1 下有两张图片时。
让我们看看发生了什么。
在我的循环中,当图像同步时,i[1]
首先具有值 1
。但是,当第二个图像访问该值时,它已被结束其迭代的第一个图像更改。
我们通过在 end do
之前添加一个额外的同步语句来解决这个小问题。
这个程序与问题之一有什么关系?在远程图像上测试值和更新它的图像之间同样缺乏同步。
在同步和其他图像测试值 co_missionAccomplished[1]
之间,第一张图像可能会四处奔波并更新 counter
,然后 co_missionAccomplished
。某些图像可能会在第一次迭代时看到退出状态。
下面的Coarray代码出现了一个奇怪的现象
program strange
implicit none
integer :: counter = 0
logical :: co_missionAccomplished[*]
co_missionAccomplished = .false.
sync all
do
if (this_image()==1) then
counter = counter+1
if (counter==2) co_missionAccomplished = .true.
sync images(*)
else
sync images(1)
end if
if (co_missionAccomplished[1]) exit
cycle
end do
write(*,*) "missionAccomplished on image ", this_image()
end program strange
这个程序永远不会结束,因为循环内任何超过 1 的计数器阈值似乎都存在死锁。该代码使用 Intel Fortran 2018 Windows OS 编译,具有以下标志:
ifort /debug /Qcoarray=shared /standard-semantics /traceback /gen-interfaces /check /fpe:0 normal.f90 -o run.exe
同样的代码,使用 DO WHILE 构造,也出现同样的现象:
program strange
implicit none
integer :: counter = 0
logical :: co_missionAccomplished[*]
co_missionAccomplished = .true.
sync all
do while(co_missionAccomplished[1])
if (this_image()==1) then
counter = counter+1
if (counter==2) co_missionAccomplished = .false.
sync images(*)
else
sync images(1)
end if
end do
write(*,*) "missionAccomplished on image ", this_image()
end program strange
这现在看起来太微不足道了,不可能成为编译器错误,所以我可能遗漏了一些关于并行 do 循环的重要信息。感谢您的帮助。
更新:
在上面的DO-CYCLE-EXIT 示例程序中的CYCLE 语句之前添加SYNC ALL 语句解决了死锁。此外,在 DO WHILE 语句之后的 SYNC ALL 语句作为块的第一行解决了死锁。显然,在上述任何一种情况下,所有图像都必须同步以避免在每个循环周期之前出现死锁。
关于"This seems now too trivial to be a compiler bug",您可能会惊讶于编译器如何错误地处理看似微不足道的事情。与 coarrays 相关的事情很少。
考虑以下相关程序:
implicit none
integer i[*]
do i=1,1
sync all
print '(I1)', i[1]
end do
end
我得到了最初令人惊讶的输出
1
2
当 运行 在 ifort 2018.1 下有两张图片时。
让我们看看发生了什么。
在我的循环中,当图像同步时,i[1]
首先具有值 1
。但是,当第二个图像访问该值时,它已被结束其迭代的第一个图像更改。
我们通过在 end do
之前添加一个额外的同步语句来解决这个小问题。
这个程序与问题之一有什么关系?在远程图像上测试值和更新它的图像之间同样缺乏同步。
在同步和其他图像测试值 co_missionAccomplished[1]
之间,第一张图像可能会四处奔波并更新 counter
,然后 co_missionAccomplished
。某些图像可能会在第一次迭代时看到退出状态。