传递大小作为参数VS在Fortran过程中假设形状

10

我正在尝试决定这两个选项中哪一个是最好的:

subroutine sqtrace( Msize, Matrix, Value )
  integer, intent(in)  :: Msize
  real*8,  intent(in)  :: Matrix(Msize, Msize)
  real*8,  intent(out) :: Value

  [instructions...]

end subroutine sqtrace

VS

subroutine sqtrace( Matrix, Value )
  real*8,  intent(in)  :: Matrix(:,:)
  real*8,  intent(out) :: Value

  if ( size(Matrix,1) /= size(Matrix,2) ) then
    [error case instructions]
  end if

  [instructions...]

end subroutine sqtrace

我了解到,当您使用警告进行编译时,第一种情况应在编译时自动检查是否调用sqtrace与指定大小相符。然而,我不知道当给定的参数是可分配的时,编译器是否可以在这些检查中执行,例如(更多地取决于其他在运行时确定的事物)。第二种方法需要显式接口并具有更多代码(检查),但似乎可以捕获更多错误。
每种方法使用的优缺点是什么,在哪些情况下应该选择其中之一?

@VladimirF 好的,我会考虑下次。我使用f90标签是因为我认为在f70中不存在假定形状。无论如何,你为什么说它不符合f90标准?有什么问题吗? - Nordico
1
我理解当您使用警告进行编译时,第一种情况应该在编译时自动检查调用sqtrace是否符合所指示的大小。也许,如果您使用模块并且使用正确的编译器,这可能会发生。通常不会进行任何检查。无论如何,在调用点处的大小在编译时可能是未知的。显式大小参数来自旧时代,当时大多数时间没有对参数进行检查。 - Vladimir F Героям слава
我觉得如果我想要对这两种形式给出一个好的答案,可能需要写很多段落。不过这也许更多地反映了我的回答能力有限,而不是问题本身。 - francescalus
1
@francescalus 不,这确实是一个广泛的问题。问题在于我发现自己经常在不明确的情况下不断地切换编程方式。我感觉缺少某种知识来帮助我开发如何使用它的标准,但具体是什么知识并不清楚。 - Nordico
1
我认为,强制调用程序传递一个多余的大小参数需要有一个真正令人信服的理由。我看不出有任何理由。 - agentp
显示剩余3条评论
1个回答

16

首先,一些术语。考虑声明为虚拟参数的 dummy arguments。

real :: a(n)                ! An explicit shape array
real :: b(:)                ! An assumed shape array
real, allocatable :: c(:)   ! A deferred shape array (allocatable)
real, pointer :: d(:)       ! A deferred shape array (pointer)
real :: e(*)                ! An assumed size array
real :: f(..)               ! An assumed rank array/scalar

我不会回答哪一个在特定情况下更好,但只是详细介绍一些重要特征,如果有选择,则留给程序员。粗略地(且不正确地),许多人将显式形状数组视为“Fortran 77”,将隐式和推迟的形状数组视为“Fortran 90 +”。

假设大小和假设等级参数超出此问题和答案的范围。


形状:

  • 显式形状数组的形状遵循其声明;
  • 隐式形状数组虚拟参数的形状为实际参数的形状;
  • 推迟的形状虚拟参数的形状可能未定义,在过程中变为定义或与实际参数相同。

连续性:

  • 显式形状数组仅是连续的;
  • 假设形状数组虚拟参数的连续性与关联的实际参数有关;
  • 推迟的形状虚拟参数可能是实际参数,也可能取决于过程的执行。

实参的限制:

  • 与显式形状数组关联的实参必须至少具有与虚拟参数相同的元素数量;
  • 与假定形状数组关联的实参本身不能是假定大小的;
  • 与假设或推迟的形状数组相关的实际参数必须具有与虚拟参数相同的秩。

调用范围中的接口:

  • 如果虚拟参数是隐式或推迟形状,则引用范围必须对该过程具有访问明确接口。

考虑real a(6)。这可能是虚拟参数的实际参数

real b(3)
real c(2,3)
real d(:)   ! With an explicit interface available

a(1::2) 可能与 b 相关联,但是由于b是连续的,所以会涉及复制输入/输出。 与 d 相关联时,不一定需要涉及复制输入/输出,但可能会涉及。

还有很多其他方面,但希望这是一个最初的高层介绍。


感谢您的概述!看起来这些是由您编制的,但您是否知道是否有任何源材料明确介绍不同类型的数组之间的差异以及在何种情况下使用其中之一?我读过的所有Fortran书籍通常只是单独介绍它们,并没有清晰列出这些区别。如果我想深入了解,我应该去哪里查找? - Nordico
1
Fortran标准文档在这类文件中实际上相当易读,一旦您对概念有了合理的理解。有些地方缺乏交叉引用,但人们可以很快熟悉它们。或者,如果人们继续在这里提出好问题,我建议跟随它们。 - francescalus
@Eular,可能会存在性能差异,但人们预计这应该与过程引用的一般开销相当。主要的实际性能差异将在连续性方面体现:显式形状虚拟参数始终是连续的(这可能涉及制作临时副本)。 - francescalus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接