【发布时间】:2020-03-04 21:40:18
【问题描述】:
当将数组部分传递给 Fortran 中的子例程时,例如f(a, b, c(2:5,4:6))(都是二维数组),程序是先做一个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)。
这是一个电话,auxp(5) 和相同的Gv:
完整的子程序。图片,而不是文字。
【问题讨论】:
-
这真的取决于 Fortran 子例程(您没有显示)。 Fortran 还可以为非连续数组传递数组描述符。
-
@VladimirF 我添加了一些虚假的,类似于我在 Fortran 代码中看到的示例。如果没有,请考虑内置的
matmul(),这也很有趣(对我来说)。我也有类似x(1:2,:)=matmul(y,z(1:2,:))的东西。但我对传递数组切片的任何情况都很感兴趣:这是一个副本吗? -
你用的是什么编译器? gfortran 有一个选项可以告诉您何时创建临时数组。
-
上床睡觉,但简短的回答是您最初的问题没有答案,因为 Fortran 标准没有说明是否需要制作副本 - 它只说明了结果应该是什么。这对于 Fortran 来说很常见,只要结果正确,编译器就可以随意实现它。因此,一个编译器可以制作副本,而另一个编译器可能不会。同一个编译器的不同版本可能会做不同的事情。您只能依赖结果是什么,而不是如何实现该结果。
-
@ja72 我不使用英特尔编译器,但我想它类似于上面 cmets 中某处提到的 g++。但是,是的,这非常有用,并且(部分)得出了结论。