What should the default access be for an associate name defined in an OpenMP loop?

General OpenMP discussion
Forum rules
The OpenMP Forums are now closed to new posts. Please visit Stack Overflow if you are in need of help: https://stackoverflow.com/questions/tagged/openmp
Posts: 1
Joined: Tue Dec 01, 2020 7:20 am

What should the default access be for an associate name defined in an OpenMP loop?

Post by Mark.Lewy »

I originally posted this on the Intel Fortran forum, but I think this applies generally.

I've tried to find out what this is in both the Fortran and OpenMP standards, but haven't found anything relevant.

Consider this Fortran code fragment:

Code: Select all

        ! 1 - find duplicates
        !$omp parallel do default(none) &
        !$omp & shared(lnodes, duplicate_of, nlinks, nnods) &
        !$omp & private(j, us_node, ds_node) schedule(dynamic)
        do i = 1, nlinks
            ! Why not ASSOCIATE? Looks like the associate names get shared in debug builds!
            us_node = lnodes(link_end_us, i)
            ds_node = lnodes(link_end_ds, i)

            if (us_node > nnods .or. ds_node > nnods) cycle ! ignore links to outfalls

            do j = 1, i - 1
                if (lnodes(link_end_us, j) == us_node .and. lnodes(link_end_ds, j) == ds_node) then
                    duplicate_of(i) = j
                else if (lnodes(link_end_ds, j) == us_node .and. lnodes(link_end_us, j) == ds_node) then
                    duplicate_of(i) = -j ! < 0 means reversed orientation
                end if
            end do
        end do
The original code had us_node and ds_node defined as associate names in an associate-block, but you can see that I found that these were being shared between loop iterations in recent Intel Fortran versions. My expectation would be that associate-names should be private to an iteration. Also, unsurprisingly, you cannot specify the associate-names in the private clause of the OpenMP do loop, as they aren't declared. Obviously, you can code around this by either having temporary private variables or pointers, but that seems to defeat the object of associate.

Have I missed something in the standard or should this be something that needs to be added to it?

Posts: 9
Joined: Thu Jan 08, 2009 7:39 pm

Re: What should the default access be for an associate name defined in an OpenMP loop?

Post by kli »

The specification states that
An associate name that may appear in a variable definition context is shared if its association occurs outside of the construct and otherwise it has the same data-sharing attribute as the selector with which it is associated. [304:11-13]
If the associate construct encloses the parallel construct, the association between the associate name and the original variable (i.e. the selector) is established before entering the parallel region. The specification states that the association is preserved throughout the entire associate block.

Posts: 1
Joined: Thu Jan 07, 2021 1:57 am

Re: What should the default access be for an associate name defined in an OpenMP loop?

Post by martin_cfd »

I had the same problem with associate within openmp. I am glad that openmp5.1 now supports associate and block, though I was surprised to learn that this took more than 10 years after those constructs have been introduced.

Regarding the data-sharing attributes of associate-name in an openmp block, I think the situation is a bit more complicated. Consider something like "associate(x => array(i))", where array is shared and i is private. The memory location of array should remain shared, as stated by the standard. But "x", which is not a variable in its own right, must still be represented in memory (just a simple pointer, a class header, an array header, etc.) What about this piece of data, should it be shared or private. In my opinion, each thread should have its own reference into array, and thus the pointer data (or however it is represented by the fortran processor) must be thread-private. Otherwise each thread would overwrite another threads view into array, which just does not make any sense?

So if I do something like

Code: Select all

!$omp parallel do default(shared) private(i)
do i = 1,N
   associate(x => array(i))
   	x = i
   end associate
end do
!$omp end parallel do
I can expect that each thread writes into the shared array, and the result is array(i)=i for i=1..N. But that is not what ifort is doing as the "pointer" x is also shared, it might happen that i is written to array(i_of_some_other_thread), if "x" has been updated in the meantime. Is this a bug or is it standard-conforming (wrt 5.1)?