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

What is the effect of violating the contiguity attribute of a dummy argument?

Arjen_Markus
Honored Contributor I
355 Views

Hello,

I am experimenting with the CONTIGUOUS attribute and I found to my surprise that passing a non-contiguous array section via a dummy argument that does have this attribute makes no difference. So I wonder if it should - for instance lead to a runtime error message - or not. I compiled the program below with the flag -check:all to see if any runtime error or warning is issued and none is (using Intel Fortran 15). The program works as if this attribute were not present.

Can someone enlighten me? (I can imagine that the attribute is recognised but does not lead to more efficient code ...)

! chktemp.f90 --
!
module temp
contains
subroutine mytemp( a, n )
    real, contiguous, dimension(:) :: a
    integer, intent(in) :: n

    a(1:n) = 1.0
end subroutine
end module temp

program chktemp
    use temp
    implicit none

    real, dimension(10,10) :: aha

    aha = 0.0

    call mytemp( aha(1,:), size(aha(1,:)) )

    write(*,'(10f5.2)') aha
end program chktemp

 

 

0 Kudos
4 Replies
jimdempseyatthecove
Honored Contributor III
355 Views

Try making subroutine mytemp an external subroutine placed into a library...
and where the library is not subject to multi-file inlining (disable multi-file ipo).

I suspect that the compiler optimization of inlining the code may have circumvented you attempt at discovery as to the consequences of violation of your contract.

Jim Dempsey

0 Kudos
Arjen_Markus
Honored Contributor I
355 Views

I did that - the module is now in one file and the program is in another and via a series of commands a library and a program using that library are built. But it made no difference. The program still works as if there was no CONTIGUOUS.

0 Kudos
Lorri_M_Intel
Employee
355 Views

Because the compiler knows that the dummy argument is expected to be contiguous, it makes a temporary (contiguous) array and does copy in/copy out around the routine call.

What you could try is to have a completely separate subroutine, not in a module and without an interface, and see what happens.

            --Lorri

0 Kudos
Arjen_Markus
Honored Contributor I
355 Views

Thanks for the suggestion, but I need to provide an interface for the routine - I tried it without and that predictably crashed :).

Of course I can cheat a bit ... trying that now. Oh, the output is wrong now:

 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00

The funny thing is I expected that the option -check:all would lead to at least messages about temporary arrays (something that does happen in a different version of the program, which I specifically set up for that type of things, as an illustration), but these did not appear.

Trying with the contiguous attribute in the interface: no warning, but the result is correct now.

Just to allow someone to repeat the experiment, here are the two source files:

! chktemp.f90 --
!
program chktemp
    implicit none

    interface
        subroutine mytemp( a, n )
            real, dimension(:) :: a ! Cheat: no contiguous attribute
            integer :: n
        end subroutine mytemp
    end interface

    real, dimension(10,10) :: aha

    aha = 0.0

    call mytemp( aha(1,:), size(aha(1,:)) )

    write(*,'(10f5.2)') aha
end program chktemp

and the code for the library:

! templib.f90 --
!
!module temp
!contains
subroutine mytemp( a, n )
    real, contiguous, dimension(:) :: a
    integer, intent(in) :: n

    a(1:n) = 1.0
end subroutine
!end module temp

 

0 Kudos
Reply