以下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语句,作为块的第一行解决了死锁。显然,在上述任何一种情况下,必须同步所有图像以避免在循环的每个循环之前发生死锁。
答案 0 :(得分:1)
关于“这似乎现在太过微不足以成为一个编译器错误”,你可能会对编译器如何错误地处理看似微不足道的事情感到非常惊讶。与coarray有关的几件事情都是微不足道的。
考虑以下相关程序:
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
。某些图像可能会在第一次迭代中看到退出状态。