数据竞争
如果我们通过多个image同时对某一个image进行修改,此时会发生数据竞争。例如其他的image同时对image1进行累加操作,当同时有多个image想要执行该操作时,就会出现错误。
program main
implicit none
integer::id,np,i
integer::a[*]
id = this_image()
np = num_images()
a=0
do i = 1, np
a[i]=a[i]+1
end do
sync all
write(*,*)"this image=",id,"a",a
end program main
多次运行就会发现结果并不正确,也不相同
$ fpm run --compiler="caf" --runner="cafrun -n 4"
this image= 2 a 4
this image= 3 a 4
this image= 4 a 3
this image= 1 a 2
$ fpm run --compiler="caf" --runner="cafrun -n 4"
this image= 4 a 3
this image= 1 a 2
this image= 2 a 4
this image= 3 a 3
所以此处我们需要的a[i]=a[i]+1
这条语句同时只能被一个image执行。
critical
通过critical
块语句,可以直接保证在该区域只有一个image执行
program main
implicit none
integer::id,np,i
integer::a[*]
id = this_image()
np = num_images()
a=0
do i = 1, np
critical
a[i]=a[i]+1
end critical
end do
sync all
write(*,*)"this image=",id,"a",a
end program main
$ fpm run --compiler="caf" --runner="cafrun -n 4"
this image= 3 a 4
this image= 4 a 4
this image= 1 a 4
this image= 2 a 4
原子操作
Fortran内置函数中还提供了原子操作的函数,通过这些函数,可以实现上述功能
program main
implicit none
integer::id,np,i
integer::a[*]
id = this_image()
np = num_images()
a=0
do i = 1, np
call atomic_add(a[i],1)
end do
sync all
write(*,*)"this image=",id,"a",a
end program main
锁
使用lock
语句也可以实现该功能
program main
use iso_fortran_env
implicit none
integer::id,np,i
integer::a[*]
type(lock_type)::lock_a[*]
id = this_image()
np = num_images()
a=0
do i = 1, np
lock(lock_a[i])
a[i]=a[i]+1
unlock(lock_a[i])
end do
sync all
write(*,*)"this image=",id,"a",a
end program main
- 使用
lock
的时候要注意unlock