- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
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
contains
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
#endif
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
#else
write(*,*) is_contiguous(myvect), intloc(c_loc(myvect)), myvect
do i=1,size(myvect)
#endif
write(*,*) intloc(c_loc(myvect(i)))
enddo
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
allocate(vect(10))
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)))
enddo
write(*,*) '--> Stride array'
write(*,*) intloc(c_loc(subvect)), subvect
do i=1,5
write(*,*) intloc(c_loc(subvect(i)))
enddo
call dumvect(subvect)
deallocate(vect)
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!
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
program Console1
implicit none
INTEGER, CONTIGUOUS, POINTER :: ap(:)
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.
ALLOCATE(ip(10))
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page