使用save openmp线程使Fortran子例程安全

时间:2019-11-21 19:17:02

标签: fortran openmp

我正在使用netlib LSODAR子例程来集成ODE。其代码为enter image description here。该代码在F77中,并使用save语句和DATA构造。我不能只删除它们,并且代码要经过很长的时间,并且需要用每个选项进行编辑。我的代码需要运行多个这些集成,因此我想使用openmp来并行化代码。有什么办法可以使这些代码成为线程安全的?我已经将所有函数和子例程都递归了,并将所有输入变量添加到了子例程private / firstprivate,但这没有帮助。任何帮助表示赞赏。如果还有其他线程安全的替代方法也可以。

一个样本将是

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

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

1 个答案:

答案 0 :(得分:0)

在没有实际示例说明您想要实现什么以及并行化应如何表现的情况下,很难回答这个问题。

我可以给出一个一般性的提示,以查看将数据私有化的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的线程专用副本中。