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

Copy of allocatable array component of a coindexed object in a subroutine with derived type dummy arguments fails

John_D_6
New Contributor I
1,704 Views

Hi,

here's another bug report about the Coarray implementation of the Intel Compiler (version 15.0.2). The following code fails with a segfault:

module arrays
  implicit none

  type b
    real,allocatable,dimension(:) :: c
  end type

  contains

  subroutine arraycopyinderivedtype(d,s)
    type(b),intent(out) :: d
    type(b),intent(in)  :: s

    if (.not.allocated(d%c)) allocate(d%c(size(s%c)))
    d%c=s%c
  end subroutine
end module

program coarraybug
  use arrays
  implicit none


  type(b),codimension
  • :: v,v0 type(b) :: t,t0 integer image image=this_image() if (image.eq.1) then allocate(v%c(2)) v%c=image allocate(v0%c(2)) v0%c=image print*,'image,v,v0=',image,v,v0 endif sync all if (image.eq.2) then write(unit=*,fmt='(a)')'Testing copy of allocatable array component of derived type coarray in the main program..' if (.not.allocated(t0%c)) allocate(t0%c(size(v0[1]%c))) t0%c=v0[1]%c print*,'t0=',t0 write(unit=*,fmt='(a)')'Testing copy of allocatable array component of derived type coarray in subroutine with derived type dummy arguments..' call arraycopyinderivedtype(t,v[1]) print*,'t=',t endif end
  • Cheers,
    John

    ---
    John Donners | Senior consultant Supercomputing | SURFsara | Netherlands | www.surfsara.nl |

    0 Kudos
    14 Replies
    Michael_S_17
    New Contributor I
    1,704 Views

    Hi,

    I believe, from my own programming experiences (with the Intel compiler), that this does not work. But I am not sure if that is a compiler failure. In case nobody knows something better, I will produce a small working program to do something similar. (I already have a working code, but it's part of a framework). Please give me a couple of days for this.

    best regards

    Michael Siehl

    0 Kudos
    Michael_S_17
    New Contributor I
    1,704 Views

    Hi,

    with only some minor changes the code now runs and gives the expected output.

    regards

    michael

     

    module arrays
      implicit none

      type b
        real,allocatable,dimension(:) :: c
      end type

      contains

      subroutine arraycopyinderivedtype(d,s,intImage)
        type(b),intent(out) :: d
        !type(b),intent(in)  :: s
        type(b),codimension

  • , intent(in)  :: s
        integer, intent(in) :: intImage
  •     ! if (.not.allocated(d%c)) allocate(d%c(size(s%c)))
        ! d%c=s%c
        if (.not.allocated(d%c)) allocate(d%c(size(s[intImage]%c)))
        d%c=s[intImage]%c

      end subroutine
    end module


    program coarraybug
      use arrays
      implicit none


      type(b),codimension

  • :: v,v0
      type(b) :: t,t0
      integer image
  •   image=this_image()

      if (image.eq.1) then
        allocate(v%c(2))
        v%c=image
        allocate(v0%c(2))
        v0%c=image
        print*,'image,v,v0=',image,v,v0
      endif

      sync all

      if (image.eq.2) then
        write(unit=*,fmt='(a)')'Testing copy of allocatable array component of derived type coarray in the main program..'
        if (.not.allocated(t0%c)) allocate(t0%c(size(v0[1]%c)))
        t0%c=v0[1]%c
        print*,'t0=',t0

        write(unit=*,fmt='(a)')'Testing copy of allocatable array component of derived type coarray in subroutine with derived type dummy arguments..'
        !call arraycopyinderivedtype(t,v[1])
        call arraycopyinderivedtype(t,v,1) ! Image 1
        print*,'t=',t
      endif

    end

     
     image,v,v0=           1   1.000000       1.000000       1.000000    
       1.000000    
    Testing copy of allocatable array component of derived type coarray in the main program..
     t0=   1.000000       1.000000    
    Testing copy of allocatable array component of derived type coarray in subroutine with derived type dummy arguments..
     t=   1.000000       1.000000   

    0 Kudos
    John_D_6
    New Contributor I
    1,704 Views

    Hi Michael,

    many thanks, that's a nice workaround! I should be able to get my code working with your tip.

    However, I do think that this is a problem with the compiler, since it should be possible to pass a coindexed object to a subroutine as a non-coarray dummy argument (see pg. 8, the next-to-last paragraph). Also, the original example has a bit more flexibility, since:

    • the s-argument can be a local variable as well as a coindexed object.
    • it can be used as a definition for the assignment operator for the derived type b (the intrinsic assignment for derived type b fails as well with an error).

    So hopefully the original example can still be accepted as a bug report.

    0 Kudos
    Steven_L_Intel1
    Employee
    1,704 Views

    We'll take a look at this.

    0 Kudos
    John_D_6
    New Contributor I
    1,704 Views

    many thanks for picking this up.

    0 Kudos
    jimdempseyatthecove
    Honored Contributor III
    1,704 Views

    Steve,

    Assume you pass "a coindexed object (member variable) to a subroutine as a non-coarray dummy argument" that has inout attribute, and further assume the subroutine contains other co-array statements, including sync all. However, in the scope of the section of the subroutine the dummy variable had not changed from entry, but an external process made the change before the sync all. Is the dummy argument to be re-synched (changed)?

    I hope my query is clear.

    In the above case, as an example a scalar dummy, externally (memory-wise) would behave as volatile across change and synch all, but code-wise (to the compiler) would be assumed non-volatile. All kinds of mischief could occur.

    Jim Dempsey

    0 Kudos
    Steven_L_Intel1
    Employee
    1,704 Views

    To Jim's question, the language rules would generally forbid changing the value of an associated argument except through the dummy, though there would be exceptions such as TARGET. Practically speaking, the compiler would do copy-in/copy-out so such changes are unlikely. An application that did this would be poorly written.

    0 Kudos
    Steven_L_Intel1
    Employee
    1,704 Views

    This is a known issue, issue ID is DPD200255059. There is an error in the original program in that it allocates the coarray only on image 1. This is incorrect - the language requires that you allocate the coarray to the same coshape on every image. However, when I fix that problem the error still occurs. Sometimes I get the segfault, sometimes bad values.

    0 Kudos
    Michael_S_17
    New Contributor I
    1,704 Views

    >>There is an error in the original program in that it allocates the coarray only on image 1. This is incorrect - the language requires that you >>allocate the coarray to the same coshape on every image.

    Hi,

    I think this is not true here. While the above used coarrays v and v0 are indeed declared on all Images, their allocatable components are not and they do not have to be (allocated on every image). This is what Aleksandar Donev calls non-symmetric objects in his Rationale for Co-Arrays in Fortran 2008 paper. (And it is, in my opinion, a reason while main arguments of a Group of Rice University for a different coarray implementation do not hold). While the use of such non-symmetric coarrays brings additional burden to the programmer, it already gives incredible flexibility to what we already can do with Coarray Fortran today. It even allows an MPMD-style of parallel software development with Fortran 2008, instead of the SPMD-style of the common coarrays (symmetric coarrays). I personally use these extensively and exclusively, and have made very good experiences with Intels ifort support of such non-symmetric coarrays. (I currently can't detect any limitations in my own programming).

    Still, I do agree with John in that I would certainly appreciate every additional (or undiscovered) feature too. However, I am not familiar with the according passage of the standards text yet, so I can't tell if there is something missing with Intels current implementation.

    BTW, even the changed and now working code is not the way I would suggest how to use such non-symmetric coarrays, because this is way too much error-prone. In production code you should completely encapsulate (private) the access to allocatable (or pointer) components of derived type coarrays, e.g. because you can't never be sure there is something allocated on the foreign image. I will code a small working program the next days to show basically what I mean.

    best regards

    michael

    0 Kudos
    Steven_L_Intel1
    Employee
    1,704 Views

    Sorry, you are correct. When I first looked at it I thought the coarrays themselves were allocatable. 

    0 Kudos
    Michael_S_17
    New Contributor I
    1,704 Views

    To me, the most questionable line in the original code is:

    call arraycopyinderivedtype(t,v[1])

    I currently don't believe that the standard does permit an actual coarray argument with a bracket reference [ ] in it. This was also a statement in an (old) CF90 Co-array Programming Manual SR-3908 3.1 from Cray (Document Number 004-3908-001), page 7: "Bracket references cannot appear as actual arguments in subroutine calls or function calls. For example: CALL S3( Y(1,K) [IP], 100 ) ! NOT PERMITTED: BRACKET ACTUAL ".

    But I also found the text passage, John mentioned above. It's in chapter 19.4 of Modern Fortran explained, the last paragraph on page 336: "A coindexed object is permitted in most contexts, such as intrinsic operations, instrinsic assignment, input/output lists, and as an actual argument corresponding to a non-coarray dummy argument."

    best regards

    michael

    0 Kudos
    Michael_S_17
    New Contributor I
    1,704 Views

    I just tried it out. I took the original code and only left the brackets out:

    call arraycopyinderivedtype(t,v)

    The code now compiles and runs without a runtime failure. But, of course, without the brackets the actual coarray argument v now stands for the (empty) coarray on the current image. According to this situation the program execution does not deliever any output for t:

     image,v,v0=           1   1.000000       1.000000       1.000000    
       1.000000    
    Testing copy of allocatable array component of derived type coarray in the main program..
     t0=   1.000000       1.000000    
    Testing copy of allocatable array component of derived type coarray in subroutine with derived type dummy arguments..
     t=

    This is further convincing, that ifort just can't handle the brackets. According to chapter 19.4 of Modern Fortran explained it should be possible. But see also the last sentence of chapter 19.8.1: '...if an actual argument is a coindexed object with an allocatable ultimate component, the corresponding dummy argument must be allocatable, a pointer, or have the intent in or value attribute.' Here, they say nothing that the corresponding dummy argument might be a non-coarray (dummy argument). Therefore, I am a little bit puzzled right now.

    best regards

    michael

    0 Kudos
    Michael_S_17
    New Contributor I
    1,704 Views

    Well,

    currently I do agree with John. His original code with the brackets seems standard conforming to me now. Ifort should be able to handle a coindexed object, resp. the brackets, as an actual argument.

    best regards

    michael

    0 Kudos
    John_D_6
    New Contributor I
    1,704 Views

    Hi Michael, Steve, Jim,

    thanks for the interesting discussion.

    In section 12.5.2.4 (Ordinary dummy variables), paragraph 6 of the Fortran 2008 working document

    (http://j3-fortran.org/doc/year/10/10-007r1.pdf) it says:

    If the actual argument is a coindexed object with an allocatable ultimate component, the dummy argument shall
    have the INTENT(IN) or the VALUE attribute.

    The INTENT(IN) for coindexed objects with allocatable components is logical, since you might otherwise try to
    allocate objects on remote images unknowingly. Section 12.5.2.8 is about co-array dummy variables, so the 'Ordinary' apparently means non-coarray dummy variables.

    The code I submitted was indeed in no way an example of good coding practice, but a reduction of the compiler problem to the simplest possible form.

    About Jim's remark: that looks indeed like a race condition and it would be the responsibility of the programmer to prevent such bad coding practice.

    About the remarks in the Cray documentation: I saw that as well and it had a further
    comment that the compiler would accept it if the co-array reference was turned into
    an expression, by putting the reference between parentheses:

    CALL S3( ( Y(1,K)[IP] ), 100 )  ! PERMITTED: ACTUAL IS EXPRESSION

    I get the impression that this was more a limitation of the Cray compiler at the time
    of writing of the manual, rather than a limitation of the Fortran language specification.
    (it's also a document from 2003, so long before Coarray was an actual standard).

    0 Kudos
    Reply