使用OpenMP的Fortran模块

时间:2015-01-07 16:13:01

标签: fortran openmp

在我看来,可以用来在子程序中保存全局变量的fortran模块在使用OpenMP时不起作用。这是一个例子:

main.f90时

program main
   use mod
   implicit none
!$OMP PARALLEL private(a)
!$OMP DO
   do i=1,10
      a=i-1
      print*,"a =",a
      call echo
      print*,"b =",b
   enddo
!$OMP END DO
!$OMP END PARALLEL
end program main

echo.f90

subroutine echo
   use mod
   implicit none
   b=a+1
   !print *,a,"+1=",b
end subroutine echo

mod.f90

module mod
   integer:: i,a,b
end module mod

现在如果你在没有OpenMP的情况下编译并运行它,你得到:

a =           0
b =           1
a =           1
b =           2
a =           2

.....等。这就是你期望的

但是,如果使用openMP编译,则得到:

a =           7
b =           1
a =           6
b =           1
a =           8

.....等。这不是我想要的。我知道echo子程序正在得到一个' a'从模块,而不是私人' a'该线程有。有什么方法可以做到这一点,除了作为一个论点传递?我的模块中有很多变量,这将是乏味的。

1 个答案:

答案 0 :(得分:10)

在程序echo内,ab是区域中引用但不在构造中引用的变量 - 执行方面它们出现在匹配的!$OMP PARALLEL之间和!$OMP END PARALLEL指令,但从源头来说他们没有。因为它们是模块变量,并且在没有相反的指令的情况下,OpemMP 4.0标准的2.14.1.2中的数据共享属性规则指定了过程中的那些变量是共享的。

因此,您的示例代码具有数据争用,多个线程在b子例程内写入echo而没有同步。

您可以在模块中使用THREADPRIVATE指令来更改这些模块变量的数据共享属性。您需要同时删除a的私有规范。

从长远来看,一个更好的方法可能是通过将信息作为参数传递(可能捆绑在一起),使程序中的信息流显式地呈现给代码的读者(并且更灵活地由代码编写器配置)在派生类型中)而不是通过使用全局(模块)变量来隐藏这些流。