带有 OpenMP 的 Fortran 模块
Fortran Modules with 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'。除了将其作为参数传递之外,还有什么方法可以做到这一点吗?我的模块中有很多变量,这会很乏味。
在过程中 echo
、a
和 b
是在区域中引用但在构造中不引用的变量 - 执行明智它们出现在匹配 !$OMP PARALLEL
和 !$OMP END PARALLEL
指令,但在源代码方面他们没有。由于它们是模块变量,并且在没有相反指令的情况下,OpemMP 4.0 标准的 2.14.1.2 中的数据共享属性规则指定过程中的那些变量是共享的。
因此,您的示例代码存在数据竞争,多个线程在 echo
子例程内写入 b
,但没有同步。
您可以在模块中使用THREADPRIVATE 指令来更改那些模块变量的数据共享属性。您需要同时删除 a
的私有规范。
在长 运行 中,一个更好的方法可能是使程序中的信息流对代码的 reader 明确(代码编写者可以更灵活地配置) ,通过将信息作为参数传递(可能捆绑在派生类型中)而不是通过使用全局(模块)变量隐藏这些流。
在我看来,可用于跨子例程保存全局变量的 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'。除了将其作为参数传递之外,还有什么方法可以做到这一点吗?我的模块中有很多变量,这会很乏味。
在过程中 echo
、a
和 b
是在区域中引用但在构造中不引用的变量 - 执行明智它们出现在匹配 !$OMP PARALLEL
和 !$OMP END PARALLEL
指令,但在源代码方面他们没有。由于它们是模块变量,并且在没有相反指令的情况下,OpemMP 4.0 标准的 2.14.1.2 中的数据共享属性规则指定过程中的那些变量是共享的。
因此,您的示例代码存在数据竞争,多个线程在 echo
子例程内写入 b
,但没有同步。
您可以在模块中使用THREADPRIVATE 指令来更改那些模块变量的数据共享属性。您需要同时删除 a
的私有规范。
在长 运行 中,一个更好的方法可能是使程序中的信息流对代码的 reader 明确(代码编写者可以更灵活地配置) ,通过将信息作为参数传递(可能捆绑在派生类型中)而不是通过使用全局(模块)变量隐藏这些流。