Question on legality / implementation of Coarry construct

139 views
Skip to first unread message

Thomas Koenig

unread,
Nov 18, 2021, 5:05:44 PM11/18/21
to
I have a question regarding the legality of the following code,

Is the code below OK? More specifically, how would an MPI-based
implementation do this? The call to foo will result in a local
allocation, but how this could be broadcast to all other images
is not clear to me.

module x
implicit none
type mytype
integer :: x
end type mytype

type foobar
type(mytype), allocatable:: xyz
end type

type(foobar):: arr[*]

contains
subroutine bar()
if (mod(this_image(), 2) .eq. 1) then
call foo(arr%xyz)
else
sync all
print *, arr[this_image() - 1]%xyz%x
end if
end subroutine

subroutine foo(a)
type (mytype), intent(inout), allocatable :: a
allocate (a)
a%x = this_image()
sync all
end subroutine foo
end module x

rbader

unread,
Nov 19, 2021, 10:52:19 AM11/19/21
to
I believe this is conforming code (possibly modulo syntactic details, I haven't tried to compile it).
Note that coarrays of a type with ALLOCATABLE or POINTER components are permitted, although in general
communication performance for these components will incur additional latencies and other performance issues due to the nonsymmetric
nature of such objects.
I cannot specifically say how an MPI based implementation would need to do this, but suspect that for this usage active-target
RMA (one-sided MPI_Get on arr[...]%xyz%x with an MPI_Fence as synchronization) would provide the needed properties.
I do not understand your reference to a "broadcast" though. Your code has ~n/2 Gets on all even images to the respective neighbour.

Regards
Reinhold

Steve Lionel

unread,
Nov 19, 2021, 11:46:59 AM11/19/21
to
On 11/18/2021 5:05 PM, Thomas Koenig wrote:
> I have a question regarding the legality of the following code,
>
> Is the code below OK? More specifically, how would an MPI-based
> implementation do this? The call to foo will result in a local
> allocation, but how this could be broadcast to all other images
> is not clear to me.

That's because it isn't broadcast. When coarray arr becomes established,
each image has its own copy of component xyz (unallocated), and it is
the responsibility of each image to allocate that component (and
synchronize) before it is referenced, either in that image or another image.

--
Steve Lionel
ISO/IEC JTC1/SC22/WG5 (Fortran) Convenor
Retired Intel Fortran developer/support
Email: firstname at firstnamelastname dot com
Twitter: @DoctorFortran
LinkedIn: https://www.linkedin.com/in/stevelionel
Blog: https://stevelionel.com/drfortran
WG5: https://wg5-fortran.org

Thomas Koenig

unread,
Nov 19, 2021, 12:10:14 PM11/19/21
to
rbader <Ba...@lrz.de> schrieb:
It does the expected thing with NAG, at least, and NAG being
picky, I suspect this is OK.

> Note that coarrays
> of a type with ALLOCATABLE or POINTER components are permitted,
> although in general communication performance for these components
> will incur additional latencies and other performance issues due
> to the nonsymmetric nature of such objects.

OK.

> I cannot specifically say how an MPI based implementation would
> need to do this, but suspect that for this usage active-target
> RMA (one-sided MPI_Get on arr[...]%xyz%x with an MPI_Fence as
> synchronization) would provide the needed properties. I do not
> understand your reference to a "broadcast" though. Your code has
> ~n/2 Gets on all even images to the respective neighbour.

Sorry, wrong terminology about broadcast. Also, the question
regarding MPI was not really what I was after, some explanation
is in order.

The reason why I was asking is a design issue that we are currently
facing desiging the shared memory coarray implementation for gfortran.

To avoid all sorts of problems, the basic design allocates a large
shared memory segment and then does fork(). All coarrays are then
put into that segment, also all locally allocated allocatables
and pointers (like in the code above).

If code that knows nothing about coarrays allocates or frees
memory, it will (up to now) simply call malloc(), which will
not work. So, we are in discussion how to solve it, preferably
without an ABI change (or replacing malloc() from under
the library).

Hmm...

FortranFan

unread,
Nov 19, 2021, 4:31:25 PM11/19/21
to
On Friday, November 19, 2021 at 12:10:14 PM UTC-5, Thomas Koenig wrote:

> ..
> The reason why I was asking is a design issue that we are currently
> facing desiging the shared memory coarray implementation for gfortran. ..

To @Thomas Koenig and all the GCC/gfortran volunteers involved with this,

Will it be possible for you to announce this effort toward shared memory coarray implementation at the Fortran Discourse site?
https://fortran-lang.discourse.group/

There are many users and fans of gfortran who use the Fortran Discourse site and there are those appear to be generally unaware of the efforts with gfortran.

By better broadcasting of your effort, you will likely notice greater energy and encouragement and appreciation toward gfortran. You may even start to seed more volunteers among the user base who start to contribute more toward the gfortran development efforts.

Thanks,

rbader

unread,
Nov 19, 2021, 4:37:24 PM11/19/21
to
This indeed sounds tricky. In particular with POINTER components, there is no way
for the target (which might be a static variable, or dynamically allocated) to tell
whether it will get used in a coarray context later on.


>
> Hmm...

Thomas Koenig

unread,
Nov 19, 2021, 6:39:59 PM11/19/21
to
That is indeed a very tricky case, especially if
the pointer is to a local variable.

So, this should work, then:

module x
implicit none
type a_t
integer, pointer :: ip
end type a_t
contains
subroutine foo(a)
type (a_t) :: a[*]
integer, target :: i
i = this_image();
if (mod(i,2) == 1) then
a%ip => i
sync all
else
sync all
print *,a[i-1]%ip
end if
sync all
end subroutine foo
end module x

program y
use x
type (a_t) :: a[*]
call foo(a)
end program y

(the sync all before the end of the subroutine to make
sure that foo is still executing and a%ip is still pointing
to something valid).

This is indeed a tough nut to crack.

FortranFan

unread,
Nov 19, 2021, 7:27:26 PM11/19/21
to
On Friday, November 19, 2021 at 6:39:59 PM UTC-5, Thomas Koenig wrote:

> ..
> (the sync all before the end of the subroutine to make
> sure that foo is still executing and a%ip is still pointing
> to something valid). ..

Intuitively one would think the following would suffice, not sure yet what the standard states (will need to check):
..
if (mod(i,2) == 1) then
a%ip => i
else
print *,a[i-1]%ip
end if
sync all
..

rbader

unread,
Nov 20, 2021, 1:57:57 AM11/20/21
to
This variant is invalid due to a race condition.

Thomas Koenig

unread,
Nov 21, 2021, 9:13:40 AM11/21/21
to
FortranFan <pare...@gmail.com> schrieb:
> On Friday, November 19, 2021 at 12:10:14 PM UTC-5, Thomas Koenig wrote:
>
>> ..
>> The reason why I was asking is a design issue that we are currently
>> facing desiging the shared memory coarray implementation for gfortran. ..
>
> To @Thomas Koenig and all the GCC/gfortran volunteers involved with this,
>
> Will it be possible for you to announce this effort toward shared memory coarray implementation at the Fortran Discourse site?
> https://fortran-lang.discourse.group/

I will not post in a forum which prescribes "welcoming language".
I feel unwelcome there.

Jos Bergervoet

unread,
Nov 21, 2021, 9:48:04 AM11/21/21
to
But Thomas, in a Fortran "discourse.group" they expect you to disagree,
that's the whole point! So you are particularly welcome now.
<https://youtu.be/xpAvcGcEc0k?t=82>

--
Jos


Reply all
Reply to author
Forward
0 new messages