Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
27979 Discussions

Explicit-shape dummy array are always contiguous?




I am trying to understand whether a dummy array is contiguous or not.

More specifically, my need is to understand whether I can be sure that an array received by a Fortran routine can given as a buffer to an interoperable C function making sure that the data are contiguous in memory.

Currently, I do have explicit-shape dummy arrays and what I am experiencing with ifort (and with gfortran as well) is that non-contiguous actual arrays are copied into a temporary storage when the actual argument is not contiguous.

In fact, one may potentially send array strides to a Fortran routine, that could be not contiguous and then could cause problem when sent to a C function via a C pointer of the buffer and a total size.

I am wondering if this is required by the standard, or if it is just the current implementation in ifort.


Let us consider this reduced example

module myarray
use iso_c_binding
use iso_fortran_env
implicit none


function intloc(cptr)
implicit none
integer(kind=int64) :: intloc
type(c_ptr), intent(in) :: cptr

intloc = transfer(cptr, 1_int64)
end function intloc

subroutine dumvect(myvect)
implicit none

#if METHOD==1
! assumed-shape
integer, dimension(:), intent(in), target :: myvect
#elif METHOD==2
! assumed-share + contiguous
integer, dimension(:), intent(in), target, contiguous :: myvect
#elif METHOD==3
! explicit-shape
integer, dimension(5), intent(in), target :: myvect
#elif METHOD==4
! assumed-size
integer, dimension(*), intent(in), target :: myvect
integer :: i

write(*,*) "--> Inside routine as dummy array"
#if METHOD==4
write(*,*) is_contiguous(myvect), intloc(c_loc(myvect)), myvect(1:5)
do i=1,5
write(*,*) is_contiguous(myvect), intloc(c_loc(myvect)), myvect
do i=1,size(myvect)
  write(*,*) intloc(c_loc(myvect(i)))
end subroutine dumvect

end module myarray

program tstarrtyp
use iso_c_binding
use myarray
implicit none
integer :: i
integer, dimension(:), allocatable, target :: vect
integer, dimension(:), pointer :: subvect


vect = [ (i, i=1,10) ]
subvect => vect(1:10:2)

write(*,*) "--> Original array"
write(*,*) intloc(c_loc(vect)), vect
do i=1,10
  write(*,*) intloc(c_loc(vect(i)))

write(*,*) '--> Stride array'
write(*,*) intloc(c_loc(subvect)), subvect
do i=1,5
  write(*,*) intloc(c_loc(subvect(i)))

call dumvect(subvect)


end program tstarrtyp


Here are the results obtained with ifort 19.1.2:

METHOD Contiguous dummy (dumvect routine)
1 False
2 True
3 True
4 True


I tried the "-check arg_temp_created" as suggested by Steve, which indeed shows me when the copy is created.

The results obtained for #1 and #2 are pretty obvious, although I am not sure whether those of cases #3 and #4 are just compiler-dependent.


Thank you for your help!

0 Kudos
4 Replies
Black Belt

I do not know a simple answer to your question.

Some aspects of contiguity are processor-dependent, and some can be controlled or set using the CONTIGUOUS attribute, which is discussed in section 5.3.7 of the F2008 standard. Arguments passed to C routines in conformity with the ISO-C interoperability features may have additional properties that the programmer may depend on or apply control to. 

0 Kudos
Valued Contributor II
program Console1

    implicit none

    INTEGER, TARGET :: targ(10)
    INTEGER, POINTER :: ip(:)
    LOGICAL :: contig

    ! Invalid because ap is contiguous. A severe error is issued at compile time.
    ap => targ(1:10:2)
    ip => targ(1:10:2)
    ! contig has a value of .FALSE.
    contig = IS_CONTIGUOUS(ip)

    write(*,*) contig

    ! contig has a value of .TRUE.
    contig = IS_CONTIGUOUS(ip)
    write(*,*) contig

    end program Console1


I am having trouble understanding why you would want ap to be contiguous, and why have two pointers that point to the same array elements with a stride of 2.  

it would make the program awful to understand later on, it is like the vestiges of a horrendous common block.  


0 Kudos
Valued Contributor II
0 Kudos

By looking at Metcalf's book (last 2018 edition "incorporating Fortran 2018") §19.5 page 372 (inside the interoperability with C chapter), we can read

"Implementations usually receive explicit-shape and assumed-size arrays in contiguous storage [...] They will need to make a copy of any array argument that is not stored contiguously, unless the dummy argument is assumed-shape"

This seems confirming what I am observing. It is just the "usually" that keeps me thinking, but practically speaking I cannot image any implementation working with explicit-shape or assumed-size arrays without dealing with contiguous memory.

0 Kudos