【问题标题】:Make a Fortran subroutine with save openmp thread safe使用 save openmp 线程安全创建 Fortran 子例程
【发布时间】:2019-11-21 19:17:02
【问题描述】:

我正在使用 netlib LSODAR 子例程来集成 ODE。代码为available。该代码在 F77 中并使用保存语句和 DATA 构造。我不能只删除它们,而且代码很长,需要很长时间才能通过和编辑每个选项。我的代码需要运行多个这些集成,因此我想使用 openmp 来并行化代码。有没有办法让这些代码线程安全?我已经使所有函数和子例程递归,并将子例程的所有输入变量设为私有/第一私有,但它没有帮助。任何帮助表示赞赏。如果还有其他线程安全的替代方案也可以。

一个样本是

program main
  !$omp parallel
     call counter()
     call counter()
  !$omp end parallel
end program main

subroutine counter()
 integer i
 save i
 i = i+1
end subroutine counter

我不能干预保存语句,而且还有一些常见的块。在我的理想情况下,最后每个线程中的 i 应该是 2。但是,在这种情况下,它只会导致(处理器数量)*2。

【问题讨论】:

  • 能否提供示例代码?

标签: fortran openmp


【解决方案1】:

如果没有实际示例来说明您想要实现的目标以及并行化应该是什么样子,这有点难以回答。

我可以给出一个一般性的提示,以查看 OpenMP 构造以将数据私有化。在您的特定情况下,您希望将全局数据私有化,因此您将需要 threadprivate 指令(OpenMP API 5.0 规范中的第 2.19.2 节)和 copyin/copyout 指令(第 2.19.6 节)。

编辑: 添加代码示例后,您可以通过在代码中添加atomic 指令来使代码线程安全:

subroutine counter()
 integer i
 save i
!$omp atomic
 i = i+1
!$omp end atomic
end subroutine counter

这将确保所有线程都将更新变量的单个副本,而不会出现竞争条件。

如果您希望通过线程获得变量的一份副本,那么您必须这样做:

subroutine counter()
 integer i
 save i
!$omp threadprivate(i)
 i = i+1
end subroutine counter

然后您可以使用copyincopyout 将值移动到i 的线程私有副本中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-18
    • 2013-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-22
    • 1970-01-01
    相关资源
    最近更新 更多