Fortran中的主机关联与使用关联 [英] Host Association vs Use Association in Fortran

查看:56
本文介绍了Fortran中的主机关联与使用关联的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于何时一个人比另一个人更可贵的一般规则"吗?

Are there any "general rules" as to when one is preferable to the other?

此问题的上下文是:昨天我问了一个有关主机关联的不同问题

The context of this question is: I asked a different question regarding host association yesterday (link) and in the comments, I was advised to use host association with caution. The reason being that through host association, it is easy to inadvertently modify variables since the subroutines have unrestricted access to all variables that are declared in the module.

为了说明这一点,我将使用以下代码示例:

To illustrate this, I will use the following code example:

module mod
implicit none

real :: x

contains

subroutine sub(y)
  use other_mod, only: a

  real, intent(out) :: y

  y = a + x
  a = a + 1.
  x = x + 1.
end subroutine sub

end module mod

a x 均在 sub 中进行了修改.但是对于 x ,我需要遍历所有代码才能看到.通过查看 sub 的声明部分,可以很容易地看到 a sub 中使用(并且可能已修改)的情况.

Both aand x are modified in sub. But for x, I need to go through all the code to see this. That a is used in sub (and possibly modified) can be seen easily by looking at the declaration part of sub.

从这个意义上讲,似乎最好有两种模块:

In this sense, it seems preferable to have two kinds of modules:

  1. 一个或多个仅包含变量声明的模块(然后在需要时使用它们 )
  2. 仅包含过程和可能的参数声明但不包含变量声明的模块

这完全摆脱了变量的主机关联.

This gets rid of host association for variables altogether.

但这似乎不可行,原因有很多:

But this doesn't seem practical for a number of reasons:

  • 我可能有十二个子例程在一个模块中使用(和修改)相同的变量.每次必须使用这些变量会使代码混乱,尤其是在其中有很多变量(例如几百个)的情况下.
  • 将变量的声明从实际使用的位置分离开似乎使代码难以理解:
      要么,要么创建一个包含所有声明的巨型控制文件.如果代码很大并且使用许多变量,这可能会造成混乱.
    • 或者,为每个模块(或一组模块,如果它们依赖相同的内容)创建一个单独的控制文件.这将使代码本身更易于理解,因为 using 可以立即显示变量的来源.但这会使代码的结构复杂化,从而创建一个非常复杂的文件结构(以及相关的依赖关系结构).
    • I might have a dozen subroutines using (and modifying) the same variables in one module. Having to use these variables everytime clutters the code, especially if there are a lot of them (say a few hundred).
    • Seperating the declaration of a variable from where it is actually used seems to make the code less comprehensible:
      • Either, one creates one giant control file containing all the declarations. This could be quite confusing if the code is large and uses many variables.
      • Or, one creates a seperate control file for every module (or group of modules, if they depend on the same content). This would make the code itself better comprehensible, since using the variables immediately shows where they are coming from. But it would complicate the structure of the code, creating a vastly more complicated file structure (and accompanying dependency structure).

      最后,所有这些可以归结为:什么时候将变量声明放在使用它们的模块中(以便它们被主机关联使用)更合理?将声明外包给单独的模块更明智(以便在需要时通过使用关联使用变量)?

      In the end, all of this boils down to: When is it more sensible to put the declaration of variables in the same module in which they are used (so that they are used by host association) and when is it more sensible to outsource the declaration to a seperate module (so that the variables will be used via use association when they are needed)?

      是否有任何一般性准则,或者应根据具体情况决定?而且,如果是个案的话,为什么要选择一个理由呢?

      Are there any general guidelines or should this be decided on a case by case basis? And if it is case by case, what are the reasons to go for one over the other?

      推荐答案

      Fortran提供了几种在不同的程序单元"(主程序,外部过程和模块)之间创建,存储,使用和传递数据的方法.> 1 如您所知,每个程序单元都可以包含内部过程-通过主机关联,它们可以访问主机中包含的任何变量或过程.这通常被视为优势.正如@HighPerformanceMark在其评论中已经提到的,何时使用主机关联或使用关联的一般准则是:

      Fortran provides several ways to create, store, use, and pass data between different "program units": the main program, external procedures, and modules.1 As you know, each program unit can contain internal procedures - which, through host association, have access to any variable or procedure contained within the host. This is often seen as an advantage. As mentioned already by @HighPerformanceMark in his comment, the general guideline for when to use host-association or use-association is:

      当变量仅(或主要)由同一模块中声明的例程使用时,请使用主机关联;当您要定义要在许多模块中使用的变量时,请使用use-association.

      use host-association when variables are only (or mainly) used by routines declared in the same module, and use use-association when you want to define variables to be used in many modules

      从您的评论看来,您的主程序中的大多数或所有主机变量都可以通过每个内部过程(大约十二个子例程)进行访问.如果真是这样,那么主机关联似乎是一个非常合理的选择,并且实际上不需要显式地将参数传递给每个子例程.另一方面,如果每个子例程实际上仅使用变量的一个子集,则对其进行更明确的显示可能是合理的.

      From your comments, it sounds like most or all of the host variables in your main program are accessed by each internal procedure (about a dozen or so subroutines). If that's the case, then host-association seems like a very reasonable option, and there's really no need to pass in arguments to each subroutine explicitly. On the other hand, if each subroutine actually uses only a subset of the variables, then it might be reasonable to get more explicit about it.

      像您一样,我通常不愿意在过程中使用未在参数列表中声明的变量.部分原因是因为我喜欢args列表如何自我记录,并且可以帮助我推断代码以及其中的数据处理方式.与其他工作人员协作时,或者如果我花了一些时间离开代码并且我对它的记忆已经淡出,则更是如此.但是,我发现没有什么理由可以完全避免主机关联,只要您知道主机关联的工作原理并制定策略即可.

      Like you, I am generally uncomfortable with using variables within a procedure that haven't been declared in an argument list. This is partly because I like how the list of args is self-documenting, and it helps me to reason about the code and how data is manipulated within it. This is even more true when collaborating with other workers, or if I've spent some time away from the code and my memory of it has faded. However, I've discovered there is little reason to avoid host association altogether, as long as you are aware of how it works and have a strategy.

      实际上,我倾向于经常使用内部过程和主机关联,尤其是对于短函数/子例程.我发现将宿主轻松地视为对象",将其变量视为属性"以及任何非常类似于完成工作的对象方法"的内部过程会有所帮助.当然,这是在简化事情,但这确实是重点.

      In fact, I tend to use internal procedures and host-association quite often, especially for short functions/subroutines. I find it helpful to loosely think of the host as the "object", its variables as "attributes", and any internal procedures very much like the object's "methods" that do the work. Of course, that's simplifying things, but that's really the point.

      对于更复杂的程序,我减少了主"程序本身的主机关联数量,然后该主机关联主要是为了以适当的顺序和上下文调用各种子例程.在这种情况下,我们可以利用 use-association 的优势,并选择直接在需要的程序单元内使用模块实体(例如过程,变量,类型,参数)他们.我们可以进一步将访问限制为仅使用 only:所需的那些模块实体.这有助于提高可读性,清楚地指示数据流,并且我发现以后更新代码更为简单.您知道,继承,封装等等...但是Fortran风格..................................................................................................................................这实际上是相当不错的.

      For more complex programs I reduce the amount of host-association from the "main" program itself, which then exists primarily to call the various subroutines in the proper order and context. In this case, we can take advantage of use-association and choose to use module entities (such as procedures, variables, types, parameters) directly within the program unit that needs them. We can further restrict access to only those module entities that are needed with only:. This aids readability, the data flow is clearly indicated, and I find that updating the code later is more straightforward. You know, inheritance, encapsulation, and whatnot...but Fortran style. Which is actually pretty good.

      这是一个示例程序结构,适用于我以及我在Fortran中从事的中等规模的项目.我喜欢将广泛使用的(静态)参数保存在一个单独的模块(或按功能分组的一个或多个模块中)中.我将派生类型和类型绑定过程保留在另一个单独的模块中.如果有用,我将某些模块实体设为 private ,这样就无法从其他程序单元访问它们.我想就是这样.

      Here's an example program structure that works for me and the moderately-sized projects I've worked on in Fortran. I like to keep my widely-used (static) parameters in a separate module (or modules, if grouped according to function). I keep derived types and type-bound procedures in another separate module(s). If it's useful, I make certain module entities private, so that they are not accessible from other program units. And I guess that's it.

      module params
          implicit none
          public              !! All items public/accessible by default.
          integer, parameter  :: dp = kind(0.d0)
          integer, parameter  :: nrows = 3
          real(dp), parameter :: one=1.0_dp, two=2.0_dp
          ...
      end module params
      
      module types
          use params, only: dp, nrows
          implicit none
          public              !! Public by default.
          private :: dim2
          ...
          integer, parameter :: dim2 = 3
          ...
          type :: A
              integer :: id
              real(dp), dimension(nrows,dim2) :: data
              contains
              procedure, pass :: init
          end type A
          ...
          contains
          subroutine init(self, ...)
              ...
          end subroutine init
          ...
      end module types
      
      module utils
          implicit none
          private             !! Private by default.
          public :: workSub1, workSub2, subErr
          ...
          integer,save :: count=0 !! Accessible only to entities in this module.
          ...
          contains
          subroutine workSub1(...)
              ...
          end subroutine workSub1
      
          subroutine workSub2(...)
              ...
          end subroutine workSub2
      
          subroutine subErr(...)
              ...
          end subroutine subErr
      
      end module utils
      
      
      program main
          !! An example program structure.
          use params, only: dp
          implicit none
          real(dp) :: xvar, yvar, zvar
          integer  :: n, i
          logical  :: rc
      
          call execute_work_subroutines()
      
          contains                !! Internal procs inherit all vars declared or USEd.
          subroutine execute_work_subroutines()
              use types, only: A
              type(A) :: DataSet
              !! begin
              call DataSet%init(i)
              do i = 1,n
                  call workSub1(xvar,yvar,zvar,A,i,rc)
                  if (rc) call subErr(rc)
                  call workSub2(A,rc)
                  if (rc) call subErr(rc)
              enddo
          end subroutine execute_work_subroutines
      end program main
      

      1 也有子模块,但是我不熟悉它们,也不想提供误导性的信息.对于逻辑上分离大型模块,它们确实很有用.

      这篇关于Fortran中的主机关联与使用关联的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆