以下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都会出现死锁 . 该代码使用英特尔Fortran 2018 Windows操作系统编译,带有以下标志:
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语句,作为块的第一行解决了死锁 . 显然,在上述任何一种情况下,必须同步所有图像以避免在循环的每个循环之前出现死锁 .
1 回答
关于“这似乎现在太过微不足道了,无法成为一个编译器错误”,你可能会对编译器如何不正确地处理看似微不足道的事情感到非常惊讶 . 与coarray相关的几件事情都是微不足道的 .
请考虑以下相关程序:
我得到了最初令人惊讶的输出
当在ifort 2018.1下使用两个图像运行时 .
让我们来看看发生了什么 .
在我的循环中,
i[1]
在图像同步时首先具有值1
. 然而,到第二个图像访问该值时,它已被第一个图像结束其迭代所改变 .我们通过在
end do
之前添加一个额外的同步语句来解决这个小问题 .这个程序与其中一个问题有什么关系?测试远程图像上的值与更新图像之间的同步缺乏同步 .
在同步和测试
co_missionAccomplished[1]
的值的其他图像之间,第一个图像可能会四处移动并更新counter
,然后更新co_missionAccomplished
. 某些图像可能会在第一次迭代中看到退出状态 .