Neraste
Neraste

Reputation: 525

Is there any reason to pass array by first item?

In a rather old style Fortran project, I often see this pattern, when an array is passed by its first item:

program test
    implicit none
    integer :: a(10)
    a(:) = 1
    call sub(a(1), 10) ! here
contains
    subroutine sub(a, length)
        integer, intent(in) :: length
        integer, intent(in) :: a(length)
        print *, a
    end subroutine
end program

where it could be:

    call sub(a, 10) ! here

which is valid even in Fortran 77.

Note the size of the array has to be passed and used explicitly, this will not work for assumed shape array:

    subroutine sub(a)
        integer, intent(in) :: a(:)
        print *, a
    end subroutine

For me this is confusing, as the call suggests a scalar is passed to the subroutine. I suppose it works because the array is passed by reference.

Is there any reason to pass arrays like this, especially now?

Upvotes: 2

Views: 223

Answers (2)

One uses this feature when using the older interface to the non-blocking MPI routines.

Say you want to pass subarray A(10,10:19) which is a part of a bigger array A(1:100,1:100).

If you pass

use mpi
call ISend(A(10,10:19), 10, MPI_REAL, ...

you pass a temporary copy of array A and the address of the temporary copy will not be valid at the time of the MPI_Wait. Therefore, instead, you create an MPI derived type, that describes the offsets in the array to be sent and you use it as

use mpi
call ISend(A(10,10), 1, derived_type, ...

Of course, with the most modern MPI libraries and compilers you use use mpi_f08. However, most HPC codes in the wild do not use it yet.

Another solution is to use an MPI derived type that includes the absolute address of the subarray and just pass A. Sometimes it is practical, sometimes it is not. It depends on how much the subarrays passed vary throughout the code.

Be aware that there are other issues present in non-blocking MPI in the old interface and it helps if you explicitly mark the routines as ASYNCHRONOUS.

Upvotes: 3

francescalus
francescalus

Reputation: 32451

Consider the following example:

  implicit none

  integer a(2,2)
  a = RESHAPE([1,2,3,4],[2,2])

  call sub(a(2,1))
  print '(2I3)', TRANSPOSE(a)

contains

  subroutine sub(b)
    integer, intent(out) :: b(2)
    b = -1
  end subroutine sub

end

Here, the element sequence represented by the actual argument a is a(2,1), a(1,2), a(2,2), and the first two are associated with the dummy argument b.

For arrays of rank greater than one, this element sequence use may make things (much) easier to specify certain consecutive elements of the actual argument. For a rank-1 array we can write a(3:) instead of a(3), say, as the actual argument. For higher rank arrays we haven't that option.

I won't express an opinion on whether this is a good use this feature.

Upvotes: 2

Related Questions