4

When passing sections of arrays to subroutines in Fortran, e.g. f(a, b, c(2:5,4:6)) (all of them 2D arrays), does the program first make a temporary copy of c, and then pass it to the subroutine (as reference, pointer, etc), or is the whole thing dynamically handled?

I am trying to convert some Fortran code to C++, and I see calls to subroutines that have sections of arrays passed as arguments. To my knowledge, C++ doesn't allow this so I tried to circumvent this in C++ like this (mat2d = std::vector<std::vector<T>>):

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

and calling as:

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

This works but it requires the size(s), and also offsets for the cases where I want to make a generic matrix multiplication (for example). So, if Fortran first makes a copy of c(2:5,4:6) to (say) a temp(4,3) array, then I can mimic that in C++: simply make a copy to a temporary, and then pass a reference of that temporary to the function, without rows/columns/offsets. But if not... I wouldn't mind hearing other people's thoughts.


Example subroutine:

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

If my words are bad, maybe a picture with the real code will do? The arrays are auxfour(4,4), aux44(4,4), and Gv(2,2).

code

And here is a call, with auxp(5) and the same Gv:

code2

Full subroutine. Picture, not words.

sub

21
  • That really depends on the Fortran subroutine (which you do not show). Fortran can also pass array descriptors for non-contiguous arrays. Commented Mar 4, 2020 at 21:46
  • @VladimirF I've added some bogus, similar example to what I see in the Fortran code. If not, consider the builtin matmul(), which is also of interest (for me). I also have something like x(1:2,:)=matmul(y,z(1:2,:)). But I'm interested for any case where a slice of array is passed on: is that a copy, or not? Commented Mar 4, 2020 at 21:49
  • 2
    What compiler are you using? gfortran has an option that tells you when a temporary array is created. Commented Mar 4, 2020 at 22:26
  • 3
    Off to bed but the short answer is there is no answer to your initial question as the Fortran standard doesn't say whether a copy need be made or not - it only says what the result should be. This is usual for Fortran, a compiler is free to implement it anyway it wants so long as the result is correct. Thus one compiler could make a copy, another might not. Different versions of the same compiler might do different things. You can only rely on what the result is, not how getting to that result is implemented. Commented Mar 4, 2020 at 22:55
  • 1
    @ja72 I don't use Intel compiler, but I suppose it's similar to g++'s mentioned somewhere in the comments above. But, yes, that was very useful, and (partially) lead to the conclusion. Commented Mar 5, 2020 at 23:13

1 Answer 1

8

It is true that the Fortran standard does not specify the details of the passing mechanism. However, because the compilers are trying to be efficient, we can say a lot about what normally happens in practice.

The Fortran standard does not specify that arguments are passed by reference, but the rules efectively require it. However, it could always be a reference to temporary copy. The reference normally means just the memory address (pointer) of the first element. That enables the perfectly valid usage when one passes only one element and references the whole array inside the subroutine/function.

In some cases the temporary copy is virtually unavoidable.

Let's consider

real :: a(10,10)

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

then if f is

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

then there is very little the compiler can do, the temporary copy is virtually guaranteed. The same holds for

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

However, for assumed shape array

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

that is not the case. These arguments are passed using an array descriptor and can be non-contiguous and you normally won't see temporary copies for them.

Finally, if the first dimension is complete:

real :: a(2:5,10)

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

the copy is not necessary either as the subarray is contiguous in memory.


Even when a temporary is not necessary, the compiler could always make it, nothing is guaranteed. But it is not very likely in practise. Compilers try to be efficient.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.