Fortran是否复制传递给函数/子例程的数组节的副本?

问题描述 投票:1回答:1

例如,将数组的各节传递给Fortran中的子例程时, f(a, b, c(2:5,4:6))(所有都是2D数组),程序是先制作c的临时副本,然后将其传递给子例程(作为引用,指针等),还是整个事物都得到动态处理?

我正在尝试将一些Fortran代码转换为C ++,并且看到对子例程的调用,这些子例程具有作为参数传递的数组部分。据我所知,C ++不允许这样做,所以我试图在C ++中像这样(mat2d = std::vector<std::vector<T>>):

f(mat2d &a, mat2d &b, mat2d *a, int rows, int rows, int offsetx, int offsety) {...}

并呼叫为:

f(a, b, c.data(), ...)

这是可行的,但是它需要大小,并且在我要进行通用矩阵乘法的情况下也需要偏移(例如)。因此,如果Fortran首先将c(2:5,4:6)的副本复制到(例如)temp(4,3)数组中,那么我可以在C ++中模仿它:简单地将副本复制到临时文件,然后将该临时文件的引用传递给函数,没有行/列/偏移量。但是,如果没有,我不会介意听到别人的想法。


示例子例程:

subroutine f(A, B, C)
  implicit none
  real(kind(1d0)) :: A(2,2), B(2,2), C(2,2)
  C = A*B
  return
end f

如果我的单词不好,也许一张带有真实代码的图片会起作用吗?数组为auxfour(4,4)aux44(4,4)Gv(2,2)

code

这是一个电话,auxp(5)和相同的Gv

code2

完整子例程。图片,而不是文字。

sub

c++ arrays fortran
1个回答
1
投票

的确,Fortran标准未指定传递机制的详细信息。但是,由于编译器正在努力提高效率,因此我们可以说出很多实际情况。

Fortran标准未指定参数是通过引用传递的,但是规则有效地要求它。但是,它始终可以是对临时副本的引用。该引用通常仅表示第一个元素的内存地址(指针)。当一个仅传递一个元素并在子例程/函数内引用整个数组时,这将实现完全有效的用法。

在某些情况下,临时拷贝实际上是不可避免的。

让我们考虑

real :: a(10,10)

call f(a(2:5,4:6))

然后,如果f

subroutine f(c)
  real :: c(3,3)

然后编译器几乎无能为力,实际上可以保证临时副本。同样适用于

subroutine f(c)
  real :: c(3,*)

但是,对于假定的形状数组

subroutine f(c)
  real :: c(:,:)

并非如此。这些参数是使用数组描述符传递的,并且可以是非连续的,通常不会看到它们的临时副本。

最后,如果第一维完成:

real :: a(2:5,10)

call f(a(:,4:6))

也不需要复制,因为子数组在内存中是连续的。


即使不需要临时文件,编译器也总能做到,没有任何保证。但这在实践中不太可能。编译器尝试提高效率。

© www.soinside.com 2019 - 2024. All rights reserved.