Skip to content

Fortran derived type partial mapping

Ye Luo edited this page Apr 28, 2021 · 7 revisions

Trying to create a prototype to C++ vector like class in Fortran 2003. It needs to hide OpenMP enter/exit data mapping. The goal is to sort out the code pattern that is OpenMP specification compliant and works in most compilers.

Reproducers

source code

A derived type is defined as

    type, public :: OMPTargetArrayDP
      real(kind = 8), dimension(:), allocatable :: array

    subroutine allocateDPArray(this, array_size)
      implicit none
      class(OMPTargetArrayDP) :: this
      integer, intent(in) :: array_size
      allocate(this%array(array_size))
      !$omp target enter data map(alloc: this%array)
    end subroutine

    subroutine freeDPArray(this)
      implicit none
      class(OMPTargetArrayDP) :: this
      !$omp target exit data map(delete: this%array)
      deallocate(this%array)
    end subroutine

Q1: is map(alloc/delete: this%array) treated as structure mapping in the OpenMP spec? I mean both this the derived type object and its array are both mapped.

all the four reproducers differ at the offload region.

  1. reproducer allocatable_array_device.f90
! initialize values
!$omp target teams distribute parallel do map(always, from:abc%array) ! Q2: is this map correct?
do i = 1, Ntotal
  abc%array(i) = i
enddo

! do a sum
Nsum = 0
!$omp target teams distribute parallel do reduction(+: Nsum)
do i = 1, Ntotal
  Nsum = Nsum + abc%array(i)
enddo

Q3: does the abc%array behaves like C pointer mapping? The runtime finds out abc%array already mapped and avoid transfer?

  1. reproducer allocatable_array_device_isptr.f90 The second offload is separate into a separate function using device memory object.
!$omp target data use_device_ptr(abc%array)
call sum_on_device(abc%array, size(abc%array))
!$omp end target data

subroutine sum_on_device(array, array_size)
  implicit none
  integer, intent(in) :: array_size
  real(kind = 8), intent(in) :: array(1:array_size)
  integer :: i, Nsum
 
! do a sum
Nsum = 0
!$omp target teams distribute parallel do reduction(+: Nsum) is_device_ptr(array)
do i = 1, array_size
  Nsum = Nsum + array(i)
enddo

write(*,*) "Nsum = ", Nsum

if (Nsum /= 500500) stop 1
end subroutine

Q4: Is abc%array still correct?

  1. reproducer allocatable_array_device_ptr.f90 is basically allocatable_array_device.f90 but using Pointer in map.
array_ptr => abc%array
!$omp target teams distribute parallel do reduction(+: Nsum) map(tofrom: array_ptr)
  1. reproducer allocatable_array_device_ptr_isptr.f90 is basically allocatable_array_device_isptr.f90 but using Pointer in map like 3

Results from different compilers

Compiler 1 2 3 4
ifx 2021.2.0 pass wrong sum pass pass
nvfotran 21.3 SegFault SegFault pass pass
AOMP flang ROCm 4.0 Syntax Error Syntax Error Syntax Error Syntax Error
gfortran 11dev Compile error Compile error wrong sum wrong sum
XL 16.1.1 pass pass pass pass
Cray 11.0.2 wrong sum compiler error wrong sum wrong sum

GNU compile error message:

   61 | !$omp target teams distribute parallel do map(always, from:abc%array)
      |                                                           1
Error: List item ‘abc’ with allocatable components is not permitted in map clause at (1)

Cray compile error message:

Variable subobjects are not allowed as arguments for this clause or directive.