Fortran函数返回数组时的最佳做法是什么?

时间:2019-02-22 15:23:25

标签: arrays function fortran stack heap

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

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

    allocate(y(size(x))
    y = 2*x
end function

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

    y = 2*x
end function

我个人更喜欢第一个,因为调用者使用 easier 很容易,但是我不确定哪个在内存方面更好,假设数组x可以很大,我不知道不知道最好是延迟数组还是自动数组。 无论如何,这是在现代Fortran中做到这一点的好方法吗?

1 个答案:

答案 0 :(得分:4)

虽然与往常一样,答案可能取决于具体情况。

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

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

  y = 2*x
end function

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

    编写Fortran 95标准时
  • 可用;

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

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

  • 可能(也可能不需要)空间用于函数结果或堆栈上的等效临时空间。

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

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

  y = 2*x
end function

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

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

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

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

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

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