2016-06-29 41 views
0

使用静态变量在子例程中存储状态是否是一种好的做法?我心里有类似以下内容:“一些东西”使用静态变量在子例程中存储状态是否是一种好的做法?

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问题吗?

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

+3

这似乎是基于对我相当的意见。我建议使用模块或派生类型并将数据存储在那里。并使用单独的初始化或配置过程。 –

+0

借调。正如你暗示的那样,在与OpenMP并行时,这种风格会成为一种正确的皇家痛苦,它只是要求竞争条件;有一个单独的初始化程序,并将其粘贴在一个模块中。哦,datan是Fortran 66风格的,atan很好,现在你可以在参数声明中使用这个表达式。 –

+0

你是否严格谈论固定参数?使用“状态”这个词让我觉得sub可能会改变它的值(在初始调用后) – agentp

回答

1

这太长太具启发性,无法成为评论,所以我把它作为答案。它阐述了VladimirF的评论。

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

确保您的程序调用初始化子例程并最终完成子例程。对我而言,这是一个优雅地适用于将来可能会出现的一般情况的最佳做法。例如,如果需要保存子程序的状态或释放一些系统资源,则最终确定是最好的。

这将在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 
+0

有没有一种方法可以强制执行一个规则:“somesub”不能修改模块范围变量? – agentp

+0

如果你想隐藏'somesub'中的一些变量,只需将它们放在另一个'module'中作为私有变量,或者不要在'module'中使用'module'来定义'somesub'。据我所知,所有模块变量都可以被该模块中定义的所有过程访问。首先,这个'module'的目标是获取'somesub'中保存的变量,并使它们成为private''module'变量,只能通过'somesub'和初始化和finification过程访问。 – innoSPG

+1

这似乎确实是最佳做法。这有点像使用模块作为C++中的单例类。 – nbren12

相关问题