experchange > fortran

Marcin Modrzejewski (12-18-18, 09:50 PM)
Dear all, I'm trying to pass an allocatable coarray, which is a component of a user-defined type, as an argument to a subroutine. The Intel Fortran compiler (ifort 19.0.1.144) issues the error message

"If the dummy argument is a coarray, the corresponding actual argument must be a coarray and must have the VOLATILE attribute if and only if the dummy argument has the VOLATILE attribute. [X]"

when I'm trying to compile the following program

program test
type t
double precision, dimension(:), allocatable :: x[:]
end type t
type(t) :: s
call g(s%x)
contains
subroutine g(x)
double precision, dimension(:), codimension[:], allocatable :: x
allocate(x(10)[*])
if (this_image() == 1) then
x(:) = 1
sync all
else
sync all
x = x(:)[1]
end if
end subroutine g
end program test

Does that program obey the standard or is it a compiler bug? The compilation with gfortran 7.3.0 with the flag "-fcoarray=single" completes without any issues.

Thanks,
Marcin
Juergen Reuter (12-19-18, 07:26 PM)
On 12/18/18 20:50, Marcin Modrzejewski wrote:
> Dear all, I'm trying to pass an allocatable coarray, which is a component of a user-defined type, as an argument to a subroutine. The Intel Fortran compiler (ifort 19.0.1.144) issues the error message
> "If the dummy argument is a coarray, the corresponding actual argument must be a coarray and must have the VOLATILE attribute if and only if the dummy argument has the VOLATILE attribute. [X]"


[....]

> Does that program obey the standard or is it a compiler bug? The compilation with gfortran 7.3.0 with the flag "-fcoarray=single" completes without any issues.
> Thanks,
> Marcin


This also compiles with the nagfor compiler v6.2. But I don't have time
to check with the standard right now.
Michael Siehl (12-20-18, 12:21 AM)
Am Dienstag, 18. Dezember 2018 20:50:56 UTC+1 schrieb Marcin Modrzejewski:
[..]
> Does that program obey the standard or is it a compiler bug? The compilation with gfortran 7.3.0 with the flag "-fcoarray=single" completes without any issues.
> Thanks,
> Marcin


My own knowledge about coarray components is somewhat limited (I've never used them within my coding).

But your code does seem to contain severe mistakes, mainly: Your main program does declare a coarray component, while your dummy in the subroutine is a traditional allocatable coarray. Thus, the error message from ifort 19 should be correct.
FortranFan (12-20-18, 02:27 AM)
On Tuesday, December 18, 2018 at 2:50:56 PM UTC-5, Marcin Modrzejewski wrote:

> .. The Intel Fortran compiler (ifort 19.0.1.144) issues the error message
> ..
> Does that program obey the standard or is it a compiler bug? ..


@Marcin,

To me, it appears to be a compiler bug; I write this because I couldn't locate any constraints disallowing your code with ALLOCATABLE coarray dummy arguments associated with actual arguments that are components of a derived type (or anything else along similar lines) in either 18-007r1 (Fortran 2018) or 10-007r1 (Fortran 2008) documents.

Now I may be wrong but if you can, you should submit a support request at Intel Online Support Center (OSC):

Intel compiler allows and executes 2 variants of your code, one where the actual and dummy arguments are both ALLOCATABLE arrays with CODIMENSIONs of an intrinsic type and also where the actual and dummy arguments are both derived types with a component that is an ALLOCATABLE array with CODIMENSIONsof an intrinsic type. See below. So this suggests the Intel compiler dislikes an actual argument that is a coarray component of a derived type, hence my search for something in the standard that might prohibit this. But Ican't find any such thing.

--- begin variant 1 ---
program test
integer, dimension(:), allocatable :: s[:]
call g( s )
stop
contains
subroutine g( c )
integer, dimension(:), allocatable :: c[:]
integer :: i
allocate(c(10)[*])
if (this_image() == 1) then
do concurrent (i=1:size(c))
c(i) = i + 42
end do
end if
sync all
c = c(:)[1]
sync all
if ( this_image() == 1 ) then
print "(g0,t10,g0)", "Image","c"
do i = 1, num_images()
print "(g0,t10,*(g0,1x))", i, c
end do
end if
return
end subroutine
end program test
--- end variant 1 ---

--- begin variant 2 ---
program test
type t
integer, dimension(:), allocatable :: x[:]
end type t
type(t) :: s
call g( s )
stop
contains
subroutine g( c )
type(t), intent(inout) :: c
integer :: i
allocate(c%x(10)[*])
if (this_image() == 1) then
do concurrent (i=1:size(c%x))
c%x(i) = i + 42
end do
end if
sync all
c%x = c%x(:)[1]
sync all
if ( this_image() == 1 ) then
print "(g0,t10,g0)", "Image","c%x"
do i = 1, num_images()
print "(g0,t10,*(g0,1x))", i, c%x[i]
end do
end if
return
end subroutine
end program test
--- end variant 2 ---

For both these variants, the output with Intel compiler is:
Image c
1 43 44 45 46 47 48 49 50 51 52
2 43 44 45 46 47 48 49 50 51 52
3 43 44 45 46 47 48 49 50 51 52
4 43 44 45 46 47 48 49 50 51 52
5 43 44 45 46 47 48 49 50 51 52
6 43 44 45 46 47 48 49 50 51 52
7 43 44 45 46 47 48 49 50 51 52
8 43 44 45 46 47 48 49 50 51 52
Michael Siehl (12-21-18, 01:29 AM)
Am Dienstag, 18. Dezember 2018 20:50:56 UTC+1 schrieb Marcin Modrzejewski:
[..]
> Does that program obey the standard or is it a compiler bug? The compilation with gfortran 7.3.0 with the flag "-fcoarray=single" completes without any issues.
> Thanks,
> Marcin


I am not sure if the programmer should confound top-level coarrays with coarray components. Conceptually, the both do appear to be very distinguishable since derived types with coarray components are intended for direct use with OOP (inheritance and procedure polymorphism for example).

I think FortranFan's variant 1 and 2 programs or the following modificationof the original program should be the way to go:

program test
type t
double precision, dimension(:), allocatable :: x[:]
end type t
type(t) :: s
call g(s)
contains
subroutine g(s)
type (t) :: s
allocate(s%x(10)[*])
if (this_image() == 1) then
s%x(:) = 1
sync all
else
sync all
s%x = s%x(:)[1]
end if
end subroutine g
end program test

Best Regards
damian (12-21-18, 05:11 PM)
I also believe it's a compiler bug. I recommend reporting it.

On a separate note, would it be better to replace "double precision" with the following?

use iso_fortran_env, only : real64
real(real64) ...

Presumably 64-bit reals is what you're seeking. Is it guaranteed that "double precision" will provide that?

Damiani
Steve Lionel (12-21-18, 05:36 PM)
On 12/21/2018 10:11 AM, damian wrote:
> On a separate note, would it be better to replace "double precision" with the following?
> use iso_fortran_env, only : real64
> real(real64) ...
> Presumably 64-bit reals is what you're seeking. Is it guaranteed that "double precision" will provide that?


No, and using the REAL64 constant isn't what one wants here either. Use
the SELECTED_REAL_KIND intrinsic to define a named (PARAMETER) constant
for the kind, specifying the precision and/or range you require.
Anything else is implementation-dependent.
gah4 (12-21-18, 09:37 PM)
On Friday, December 21, 2018 at 7:12:01 AM UTC-8, dam...@sourceryinstitute.org wrote:
> I also believe it's a compiler bug. I recommend reporting it.


> On a separate note, would it be better to replace
> "double precision" with the following?


> use iso_fortran_env, only : real64
> real(real64) ...


> Presumably 64-bit reals is what you're seeking.
> Is it guaranteed that "double precision" will provide that?


It isn't guaranteed, but it is about as likely as the presumption
that OP is seeking 64-bits.

There is hardware where single precision is 60 or 64 bits, and
the Fortran required double precision is software implemented 120
or 128 bits. In those cases, you probably don't want double precision.

But you will likely only find those in a museum.

IEEE 754-2008 decimal floating point basic types are 64 and 128 bits,
presumably both (or neither) implemented in hardware when you are
using a compiler that knows about them.

The SELECTED_REAL_KIND idea is nice, but it is rare to know exactly
how much precision one needs (at least until it is too late).

One interesting case is the Fortran requirement that default INTEGER
and default REAL be the same size, and DOUBLE PRECISION twice that size.
(The requirement allows for some fun tricks with EQUIVALENCE to work.)

If some system implements default INTEGER as 64 bits, then it also
has to do the same for default REAL, and DOUBLE PRECISION at 128
bits. Hopefully that doesn't happen before we have good fast
hardware with 128 bit floating point.
Michael Siehl (12-22-18, 07:20 PM)
After consulting Modern Fortran Explained, it seems that I was wrong:

In it's section 'The properties of coarrays' see this statement: “The term whole coarray is used for the whole of an object that is declared as a coarray or the whole of a coarray component of a structure.”

Therefore, the error message from ifort must be wrong.

cheers
Marcin Modrzejewski (12-23-18, 05:37 AM)
On Tuesday, December 18, 2018 at 8:50:56 PM UTC+1, Marcin Modrzejewski wrote:
> Dear all, I'm trying to pass an allocatable coarray, which is a component of a user-defined type, as an argument to a subroutine. The Intel Fortran compiler (ifort 19.0.1.144) issues the error message [...]
> Does that program obey the standard or is it a compiler bug? The compilation with gfortran 7.3.0 with the flag "-fcoarray=single" completes without any issues.


Thank you all for your remarks and suggestions. I've submitted a bug report to Intel.

Interestingly, when trying to sidestep the compiler bug in ifort (with FortranFan's "variant 1" posted in this thread), I noticed something which looks like a compiler bug in gfortran. Here's a minimum example which doesn't compile with gfortran 8.2.0

program test
implicit none
integer, parameter :: F64 = selected_real_kind(p=15, r=307)
real(F64), dimension(:), allocatable :: x[:]
call g(x)
if (this_image()==1) then
print *, x
end if
contains
subroutine g(x)
real(F64), dimension(:), allocatable :: x[:]
allocate(x(10)[*])
call g2(x)
end subroutine g
subroutine g2(x)
real(F64), dimension(:) :: x[*]
integer :: k
do k = 1, 10
x(k) = 2.0_F64 * this_image()
end do
end subroutine g2
end program test

The following error message appears:

marcin@trisolaris:~/Desktop/CoArraysTest$ gfortran-8 -fcoarray=lib example-gfortran.f90 -lcaf_mpi
example-gfortran.f90:13:0:

call g2(x)

internal compiler error: in gfc_conv_procedure_call, at fortran/trans-expr.c:5866

The compilation completed without any errors when using the flag -fcoarray=single, i.e., not linking against OpenCoarrays. Intel Fortran also doesn't see any problem here.

Cheers
Michael Siehl (12-23-18, 02:41 PM)
Am Sonntag, 23. Dezember 2018 04:37:11 UTC+1 schrieb Marcin Modrzejewski:
[..]
> internal compiler error: in gfc_conv_procedure_call, at fortran/trans-expr.c:5866
> The compilation completed without any errors when using the flag -fcoarray=single, i.e., not linking against OpenCoarrays. Intel Fortran also doesn't see any problem here.
> Cheers


I did not compile that program previously, but after compiling it yet I see the issue with gfortran.

I am certainly wrong again, but even if gfortran does issue an internal compiler error message, there could still be a mistake with the code:

I found the following statement in Modern Fortran Explained (section 'Coarrays in procedures'): ".., the interface is required to be explicit so that the compiler knows it is passing the coarray and not just the local variable."

After some minor change with the code, the program compiles without an internal compiler error:

program test
implicit none
integer, parameter :: F64 = selected_real_kind(p=15, r=307)
real(F64), dimension(:), allocatable :: x[:]
! call g(x)
call g(x(:))
if (this_image()==1) then
print *, x
end if
contains
subroutine g(x)
real(F64), dimension(:), allocatable :: x[:]
allocate(x(10)[*])
! call g2(x)
call g2(x(:))
end subroutine g
subroutine g2(x)
real(F64), dimension(:) :: x[*]
integer :: k
do k = 1, 10
x(k) = 2.0_F64 * this_image()
end do
end subroutine g2
end program test

But then, to make the program run with gfortran, I had to apply further changes with the code:

program test
implicit none
integer, parameter :: F64 = selected_real_kind(p=15, r=307)
real(F64), dimension(:), allocatable :: x[:]
allocate(x(10)[*])
call g(x(:))
if (this_image()==1) then
print *, x
end if
contains
subroutine g(x)
real(F64), dimension(:) :: x[*]
call g2(x(:))
end subroutine g
subroutine g2(x)
real(F64), dimension(:) :: x[*]
integer :: k
do k = 1, 10
x(k) = 2.0_F64 * this_image()
end do
end subroutine g2
end program test

So there might be issues with gfortran/OpenCoarrays yet.

cheers

(Just a tip: Using Modules may help greatly with coarray programming.)
FortranFan (12-23-18, 07:37 PM)
On Sunday, December 23, 2018 at 7:41:03 AM UTC-5, Michael Siehl wrote:

> ....
> real(F64), dimension(:), allocatable :: x[:]
> ! call g(x)
> call g(x(:))
> if (this_image()==1) then
> ..
> contains
> subroutine g(x)
> real(F64), dimension(:), allocatable :: x[:]


@Michael Siehl,

Your modified code appears non-conforming: I think the use of an array section, as in 'call g(x(:))', should lead to an actual argument that does NOT have the ALLOCATABLE attribute whereas the dummy argument requires this attribute.

> .. I found the following statement in Modern Fortran Explained (section 'Coarrays in procedures'): ".., the interface is required to be explicit ..
> (Just a tip: Using Modules may help greatly with coarray programming.)


Not sure where you are going with this, OP has CONTAINed procedures and theinterfaces are thus explicit; the issues at hand with gfortran (or with Intel Fortran) are irrespective of whether MODULEs are used.

> .. even if gfortran does issue an internal compiler error message, there could still be a mistake with the code: ..


Re: "there could still be a mistake with the code" - what mistake? OP's modified code in the post dated Dec 22 appears conforming. gfortran has the problem with ICE which is always a compiler bug. But now, if it accepts your code modification with the array section, that suggests yet another issue in gfortran.
Michael Siehl (12-28-18, 04:48 PM)
That code is non-conforming, of course, nor is the code my own idea. I did simply apply the code example from the book's Figure 19.3 (the green Fortran 2008 edition) to figure out where the internal compiler error could be from. In the book, this example is directly linked with the above mentioned statement.

But I do not insist on that viewpoint because my own codes are different from that indeed.
FortranFan (12-28-18, 07:39 PM)
On Friday, December 28, 2018 at 9:48:30 AM UTC-5, Michael Siehl wrote:

> That code is non-conforming, of course, nor is the code my own idea. I did simply apply the code example from the book's Figure 19.3 (the green Fortran 2008 edition) to figure out where the internal compiler error could be from. In the book, this example is directly linked with the above mentionedstatement.
> ..


Figure 19.3 in Modern Fortran Explained (Edition published 2011 with coverage of Fortran 2008) shows dummy arguments that do not have the ALLOCATABLE attribute, so it's a different case compared to your code modification where the dummy argument is indeed ALLOCATABLE:

--- reference: your modification ---
> ....
> real(F64), dimension(:), allocatable :: x[:]
> ! call g(x)
> call g(x(:))
> if (this_image()==1) then
> ..
> contains
> subroutine g(x)
> real(F64), dimension(:), allocatable :: x[:]


Re: "In the book, this example is directly linked with the above mentioned statement", the statement in the book stresses the need for explicit interfaces and the use of MODULEs is one way to achieve this. However the two codes shown by OP indeed have explicit interfaces, so the problems encountered by OP with compilers (gfortran now and Intel Fortran initially) appear tobe different issues altogether.
Marcin Modrzejewski (12-30-18, 01:19 AM)
On Sunday, December 23, 2018 at 4:37:11 AM UTC+1, Marcin Modrzejewski wrote:
[..]
> internal compiler error: in gfc_conv_procedure_call, at fortran/trans-expr.c:5866
> The compilation completed without any errors when using the flag -fcoarray=single, i.e., not linking against OpenCoarrays. Intel Fortran also doesn't see any problem here.
> Cheers


I've added the bug corresponding to my second example to gfortran's bugzilla (bug 88624). It's confirmed to affect the compiler at least since version 4.8.

Similar Threads