Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
New Contributor III
10 Views

OpenMP with associate - define private?

Hi, I like to parallize a loop with OpenMP. For better readability I further like to use associate within this loop. In a minimum working example this looks like:

program OMP_associate
  use iso_fortran_env, only : compiler_version
  implicit none
  
  integer :: i, i_dummy(73), i_array(42,73)
  
  
  write(*,'("OMP with associate test")')
  write(*,'("Compiler version: ",a)') compiler_version()
  
  i_array = 73
  
  !$OMP parallel do private(i, i_dummy)  
  ! !$OMP parallel do private(i, i_dummy, i_ass) ! this is not accepted, because i_ass is not defined, has no type
  do i = 1, size(i_array,dim=2)
    associate (i_ass => i_array(:,i)) ! this causes a race condition, because i_ass is not declared as private
      
    ! do something
    i_dummy(i) = sum(i_ass)
    end associate
  end do
  !$OMP end parallel do
  
  write(*,'(*(i8))') i_dummy  

end program OMP_associate

The code compiles with this option fine (PSXE 2020 initial, aka 19.1.0, Windows OS):

/nologo /debug:full /Od /Qopenmp-offload /Qopenmp /warn:all /debug-parameters:used /module:"x64\Debug\\" /object:"x64\Debug\\" /Fd"x64\Debug\vc150.pdb" /traceback /check:all /libs:static /threads /dbglibs /c

At run time it fails in line 25 with multiple threads because i_ass is not private and i_dummy contains garbadge. Single threaded works fine.

OMP with associate test
Compiler version: Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 19.1.0.166 Build 20191121
********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
forrtl: error (63): output conversion error, unit -1, file CONOUT$
Image              PC                Routine            Line        Source
OMP_associate.exe  00007FF601019564  Unknown               Unknown  Unknown
OMP_associate.exe  00007FF601016683  Unknown               Unknown  Unknown
OMP_associate.exe  00007FF601013771  Unknown               Unknown  Unknown
OMP_associate.exe  00007FF60101133E  MAIN__                     25  OMP_associate.f90
OMP_associate.exe  00007FF6010AA47E  Unknown               Unknown  Unknown
OMP_associate.exe  00007FF6010AB194  Unknown               Unknown  Unknown
OMP_associate.exe  00007FF6010AB0BE  Unknown               Unknown  Unknown
OMP_associate.exe  00007FF6010AAF7E  Unknown               Unknown  Unknown
OMP_associate.exe  00007FF6010AB209  Unknown               Unknown  Unknown
KERNEL32.DLL       00007FFAD5A637E4  Unknown               Unknown  Unknown
ntdll.dll          00007FFAD85BCB81  Unknown               Unknown  Unknown

Is there a way to get the pointer associated to a variable private without using an explicitly defined pointer/target construct? Otherwise I would use a local copy...

0 Kudos
6 Replies
Highlighted
10 Views

Try:

Try:

!$omp ...
do I=...
  block
    associate(i_ass=>...
  end block
end do
!$omp end...

or

program OMP_associate
  use iso_fortran_env, only : compiler_version
  implicit none
  
  integer :: i, i_dummy(73)         ! *** remove i_array
  integer, target :: i_array(42,73) ! *** add i_array with TARGET attribute
  integer, pointer :: i_ass (:,:)      ! *** add pointer to rank 2 array         
  
  write(*,'("OMP with associate test")')
  write(*,'("Compiler version: ",a)') compiler_version()
  
  i_array = 73
  
!$OMP parallel do private(i, i_dummy, i_ass) ! *** now declare pointer as private
  do i = 1, size(i_array,dim=2)
    associate (i_ass => i_array(:,i))      
    ! do something
    i_dummy(i) = sum(i_ass)
    end associate
  end do
  !$OMP end parallel do
  
  write(*,'(*(i8))') i_dummy  

end program OMP_associate

Jim Dempsey

 

0 Kudos
Highlighted
New Contributor III
10 Views

Hi Jim, thanks for your reply

Hi Jim, thanks for your reply.

The second solution I've tried to avoid, because in my application I would have to assign many class components as targets. In your above second suggestion in line 7 it must say integer,pointer::i_ass(:), because of rank 1. Then it works fine.

However, I found a coding error of mine in the original code: In line 13 i_dummy must not be listed in the OMP private definition. Removing it, the original code runs fine although i_ass is not defined as private explicitly.

!$OMP parallel do private(i,i_dummy) !change to private(i)

The first solution of Jim would require to nest the associate within a block. Wasn't there recently a thread, where this causes problems (compiler implementation not standard)?

Are locally defined variables in blocks always treated as private in an OMP section?

Finally is this - automatically OMP private - valid for assoiated variables, too?

BR, Johannes

0 Kudos
Highlighted
New Contributor III
10 Views

UPDATE: What works fine in

UPDATE: What works fine in this simple example, fails in my complex application. I'll try to nail it down, but I'm highly suspicious for using associate within an OMP section for now. Using a block around it, fails in a different way.

While I'm working on a reproducer, has anyone knowledge, whether associate can be savely used within an OMP section? Does the standard mention something?

0 Kudos
Highlighted
10 Views

You may also consider passing

You may also consider passing the array slice to a contained procedure (or external procedure) that is called by each thread.

Jim Dempsey

0 Kudos
Highlighted
New Contributor III
10 Views

Hi Jim, yes that would be an

Hi Jim, yes that would be an idea.

I now figured out, what went wrong. In my application I made a similar mistake as in the original example. I put an array defined and allocated outside the OMP section into the private list. This caused some wierd errors and was misleading me to associated pointer. Once I got an array bounds error of a variable with the associated pointer, then an access violation in libiomp5md.dll and thirdly an error while deallocating a complete other variable - all with only slightly changing the order of some lines. I suggest that by the OMP private statement local copies have been made and that these could not be correctly finalized in OMP lib/during compilation. For sure a mistake of my own.

I wonder, if it would be possible to make the compiler identifying this error and give the user a warning?

Nevertheless, the question, whether an ASSOCIATE statement can be savely used within an OMP section, is still open. It seems to work with the Intel compiler, but might not with other compilers.

0 Kudos
Highlighted
10 Views

For allocatable arrays that

For allocatable arrays that are not allocated outside the parallel region, that are to be allocated (and deallocated) within the parallel region, use FIRSTPRIVATE as opposed to PRIVATE. I know for a fact that at least older versions of the compiler used to result in the (supposed) unallocated array descriptor initially containing junk inside the parallel region. I am not sure if this was corrected. The use of FIRSTPRIVATE copies in the unallocated state of the array descriptor.

Jim Dempsey

0 Kudos