【问题标题】:Is it good practice to store state within a subroutines using static variables?使用静态变量在子例程中存储状态是一种好习惯吗?
【发布时间】:2016-06-29 18:24:16
【问题描述】:

使用静态变量在子例程中存储状态是一种好习惯吗?我想到了以下内容:

subroutine somesub()
logical, save :: first_call = .true.


if (first_call) then
! do some stuff

first_call = .false.
end if

! ... perform standard work

end subroutine somesub

“一些东西”的例子包括:

  1. 分配工作数组。这可能最好通过自动数组来完成。
  2. 初始化需要某种运行时评估的物理/数学常数。一个很好的例子是pi = datan(1.0)*4d0
  3. 从名称列表或文本文件中读取一些参数和物理内容。

根据this question,在多线程实例中不赞成使用静态变量来存储这种状态。这会是典型 fortran 物理模拟代码中 openmp 或 mpi 的问题吗?

对于处理特定于特定子程序的物理常数和用户可修改参数,您推荐什么替代方法?

【问题讨论】:

  • 这似乎是基于我的意见。我建议使用模块或派生类型并将数据存储在那里。并使用单独的初始化或配置过程。
  • 第二。正如您所暗示的,当与 OpenMP 并行时,这种风格可能会成为一种真正的痛苦,它只是要求竞争条件;有一个单独的初始化例程并将其粘贴在一个模块中。哦,datan 是 Fortran 66 风格的,atan 很好,现在你可以把这个表达式贴在参数语句中。
  • 你说的是固定参数吗?使用术语“状态”让我认为 sub 可能会改变它的值(在初始调用之后)

标签: fortran fortran90


【解决方案1】:

这太长了,太有启发性了,不能作为评论,所以我把它作为一个答案。它详细阐述了 VladimirF 的 cmets。

如果一个子程序足够具体,有自己的一组参数,程序的任何其他部分都无法访问,则为该子程序创建一个模块。添加子程序的参数作为模块的私有实体,添加子程序本身(仅标准工作)并添加一个初始化子程序,最终添加一个终结子程序。

确保您的程序调用初始化子例程并最终调用终结子例程。对我来说,这是一个最佳实践,可以优雅地应用于您将来可能遇到的一般情况。例如,如果需要保存子程序的状态或者释放一些系统资源,finalization是最好的地方。

这将在 MPI 环境中工作得很好,其中每个实例可能有自己的子程序参数集。只要你知道什么时候调用初始化,用openmp也很方便。

您的模块可能如下所示:

module some_mod
implicit none
    private
    ! declare all the stuff that are private to your module here
    public somesub, init_somesub, finalize_somesub
contains

    subroutine somesub()
        !
        ! perform only the standard work, nothing else
        !
    end subroutine somesub

    subroutine init_somesub()
        !
        ! do only the initialization here
        !
    end subroutine init_somesub

    subroutine finalize_somesub()
        !
        ! do some stuff here to finalize if necessary
        !
    end subroutine finalize_somesub

end module some_mod

【讨论】:

  • 有没有办法强制规定somesub 不能修改模块范围变量?
  • 如果你想对somesub隐藏一些变量,只需将它们作为私有变量放在另一个module中,或者不要在定义modulemoduleusemodule定义@987654328 @。据我所知,该模块中定义的所有过程都可以访问所有模块变量。首先,这个module 的目标是获取somesub 中保存的变量,并使它们成为private module 变量,这些变量只能由somesub 访问以及初始化和完成过程。
  • 这似乎是最佳实践。这有点像在 c++ 中使用模块作为单例类。
猜你喜欢
  • 2018-02-25
  • 1970-01-01
  • 2011-04-09
  • 2013-10-13
  • 1970-01-01
  • 2019-11-20
  • 2011-09-23
  • 1970-01-01
  • 2023-02-19
相关资源
最近更新 更多