Fortran函数返回数组时的最佳实践是什么?

Man*_*ena 4 arrays heap stack fortran function

假设我想编写一个函数,该函数将一个维度的数组x作为输入,并基于该数组返回相同维度的另一个数组y(为了说明这一点,我正在使用将其乘以2的函数)。对于该代码,我有两个选择:

function times2(x) result(y)
    real, intent(in) :: x(:)
    real, allocatable :: y(:)

    allocate(y(size(x))
    y = 2*x
end function
Run Code Online (Sandbox Code Playgroud)

要么

function times2(x,n) result(y)
    real, intent(in) :: x(n)
    integer, intent(in) :: n
    real  :: y(n)

    y = 2*x
end function
Run Code Online (Sandbox Code Playgroud)

就个人而言,我更喜欢第一个,因为它更易于调用方使用,但是我不确定哪个在内存方面更好,假设数组x可以很大,我不知道成为a会更好。延迟数组或自动数组。无论如何,这是在现代Fortran中实现的最佳方法吗?

Ian*_*anH 5

也许两者都不是,尽管与这些事情一样,答案取决于特定的情况。

假设是非基本操作,我倾向于将这样的函数(在模块中)编写为:

function times2(x) result(y)
  real, intent(in) :: x(:)
  real :: y(size(x))

  y = 2*x
end function
Run Code Online (Sandbox Code Playgroud)

上面有一个假定的shape虚拟参数,带有自动函数结果。它:

  • 在编写Fortran 95标准时可用;

  • 在源代码中明确指定函数结果的大小对函数参数的依赖关系,这可能会(或可能不会)帮助您的代码阅读者了解正在发生的事情(这样的阅读器就是编译器本身,这可能会有助于优化) );

  • 可以(也可以不)避免数组值的中间副本;

  • 可能(也可能不会)需要空间来存放函数结果或堆栈上的等效临时文件。

如果该操作是元素操作(即,根据给出的实际示例,对每个元素进行相同的操作),我将编写一个元素函数。该函数的源采用标量参数,并提供不可分配的,非指针的标量结果。

elemental function times2(x) result(y)
  real, intent(in) :: x
  real :: y

  y = 2*x
end function
Run Code Online (Sandbox Code Playgroud)

当函数结果的形状(或其他属性)无法通过简单的规范表达式描述时,我通常使用延迟形状可分配函数结果。可分配的函数结果:

  • 至少需要编写Fortran 2003标准;

  • 可能需要超出严格必要的额外堆内存分配/重新分配对,这可能会(或可能不会)影响性能;

  • 可能不需要与自动结果情况一样使用堆栈,这可以(或可以不)避免在执行时出现堆栈溢出问题。

编译器实现的详细信息(包括编译器选项)会影响比较。特别是,编译器如何管理临时存储器的差异可能会使这两种方法在其对堆栈和堆分配的要求方面趋于一致。

除非有特殊要求,否则请避免使用显式形状数组伪参数。