【问题标题】:Fortran Modules with OpenMP带有 OpenMP 的 Fortran 模块
【发布时间】:2015-01-08 03:19:00
【问题描述】:

在我看来,可用于跨子例程保存全局变量的 fortran 模块在使用 OpenMP 时的工作方式不同。这是一个例子:

ma​​in.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 返回或分配b 而不是共享它会怎样,因为它是一个仅取决于a 的基本函数。我认为有几个线程正在同时修改b

标签: fortran openmp


【解决方案1】:

在过程 echoab 内部是在区域中引用但不在构造中引用的变量 - 在执行方面它们出现在匹配的 !$OMP PARALLEL!$OMP END PARALLEL 指令之间,但源明智的他们没有。由于它们是模块变量,并且在没有相反指令的情况下,OpemMP 4.0 标准的 2.14.1.2 中的数据共享属性规则指定过程中的这些变量是共享的。

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

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

从长远来看,更好的方法可能是通过将信息作为参数传递(可能捆绑在一起在派生类型中)而不是通过使用全局(模块)变量来隐藏这些流。

【讨论】:

  • 我会在明天尝试时接受它。不幸的是,我只是一名实习生,我没有权限对这段代码进行火腿。我不知道 THREADPRIVATE。听起来正是我需要的!
猜你喜欢
  • 2020-10-17
  • 1970-01-01
  • 2016-05-22
  • 1970-01-01
  • 2018-11-18
  • 2015-06-26
  • 1970-01-01
  • 2013-04-22
  • 1970-01-01
相关资源
最近更新 更多