问题
I have a 1-dimensional work array
real(8), allocatable :: work(:)
which is passed to a subroutine that operates on a 2-dimensional array
pure subroutine f(work, dim1, dim2)
real(8), intent(out) :: work(dim1, dim2)
integer, intent(in) :: dim1, dim2
...
What is the difference in the following ways of passing the array?
call f(work, dim1, dim2)
call f(work(1), dim1, dim2)
Are they the same in that they just pass the pointer to the first array element or is there some extra overhead with either call? Are there more elegant ways in modern Fortran of passing an array whose shape needs to change, without passing the dimensions explicitly, but without taking a performance hit?
I know the above looks like old Fortran but I've found it faster than declaring a two-dimensional array in the parent subroutine and passing an array section, work(:dim1,:dim2)
, to f
.
回答1:
Both example statements are forms of sequence association. The actual argument specifies a sequence of array elements, that are then associated with the elements of the dummy argument in array element order.
If work (in the calling scope) is allocated to non-zero size and has a lower bound of one, there is unlikely to be a practical difference in implementation.
In both cases, the programmer must ensure that the size of the dummy argument must be less than or equal to the size of the actual argument element sequence.
Using the whole array reference makes it clearer to readers (and perhaps the compiler) that it was the author's intent to pass an array element sequence, potentially including all the elements of the array. It also defends against the actual argument being zero size, or perhaps having a lower bound other than one.
The author's intent is far less clear when a reference to a specific element is used to designate an array element sequence.
In this specific case, because the actual argument is allocatable the compiler knows that the element sequence of the actual argument will be contiguous, and it can arrange for the dummy argument to be associated with the element sequence appropriately. In other cases, say if the actual argument was itself an assumed shape argument without the contiguous attribute, the compiler does not know that the element sequence is contiguous, and it may have to make a copy of the element sequence ahead of the call. This can have material performance impact - it is probably the reason why you found using a non-contiguous rank two array section as an actual argument to be slower.
来源:https://stackoverflow.com/questions/41813114/passing-an-array-to-a-subroutine-that-expects-a-different-shape