allocator.f90 Source File

! backends/omp/target/allocator.f90

Implements an allocator specialised to OMP target offloading


This file depends on

sourcefile~~allocator.f90~~EfferentGraph sourcefile~allocator.f90 allocator.f90 sourcefile~allocator.f90~3 allocator.f90 sourcefile~allocator.f90->sourcefile~allocator.f90~3 sourcefile~common.f90 common.f90 sourcefile~allocator.f90->sourcefile~common.f90 sourcefile~field.f90 field.f90 sourcefile~allocator.f90->sourcefile~field.f90 sourcefile~mesh.f90 mesh.f90 sourcefile~allocator.f90->sourcefile~mesh.f90 sourcefile~allocator.f90~3->sourcefile~common.f90 sourcefile~allocator.f90~3->sourcefile~field.f90 sourcefile~field.f90->sourcefile~common.f90 sourcefile~mesh.f90->sourcefile~common.f90 sourcefile~mesh.f90->sourcefile~field.f90 sourcefile~decomp_2decompfft.f90 decomp_2decompfft.f90 sourcefile~mesh.f90->sourcefile~decomp_2decompfft.f90 sourcefile~mesh_content.f90 mesh_content.f90 sourcefile~mesh.f90->sourcefile~mesh_content.f90 sourcefile~decomp_2decompfft.f90->sourcefile~mesh_content.f90 sourcefile~mesh_content.f90->sourcefile~common.f90

Files dependent on this one

sourcefile~~allocator.f90~~AfferentGraph sourcefile~allocator.f90 allocator.f90 sourcefile~backend.f90~3 backend.f90 sourcefile~backend.f90~3->sourcefile~allocator.f90

Source Code

!!! backends/omp/target/allocator.f90
!!
!! Implements an allocator specialised to OMP target offloading

module m_omptgt_allocator

  use iso_c_binding, only: c_ptr, c_f_pointer, &
                           c_sizeof, c_associated, c_null_ptr
  use omp_lib, only: omp_target_alloc, omp_target_free, &
                     omp_get_default_device, omp_get_num_devices, &
                     omp_get_initial_device

  use m_common, only: dp

  use m_allocator, only: allocator_t
  use m_mesh, only: mesh_t
  use m_field, only: field_t

  implicit none

  private
  public :: omptgt_allocator_t
  public :: omptgt_field_t

  type, extends(allocator_t) :: omptgt_allocator_t
  contains
    procedure :: create_block => create_block_omptgt
  end type omptgt_allocator_t

  interface omptgt_allocator_t
    module procedure omptgt_allocator_init
  end interface omptgt_allocator_t

  type, extends(field_t) :: omptgt_field_t
    ! A device-resident field
    integer, private :: dev_id
    type(c_ptr), private :: dev_ptr = c_null_ptr
    real(dp), pointer, private :: p_data_tgt(:) => null()
    real(dp), pointer, contiguous :: data_tgt(:, :, :) => null()
  contains
    procedure :: fill => fill_omptgt
    procedure :: get_shape => get_shape_omptgt
    procedure :: set_shape => set_shape_omptgt
    final :: omptgt_field_destroy
  end type omptgt_field_t

contains

  ! Constructor for the OMP target offload allocator
  type(omptgt_allocator_t) function omptgt_allocator_init(dims, sz) result(a)
    integer, intent(in) :: dims(3)
    integer, intent(in) :: sz

    a%allocator_t = allocator_t(dims, sz)
  end function omptgt_allocator_init

  ! Allocates a device-resident block
  function create_block_omptgt(self, next) result(ptr)
    class(omptgt_allocator_t), intent(inout) :: self
    class(field_t), pointer, intent(in) :: next
    class(field_t), pointer :: ptr

    self%next_id = self%next_id + 1
    allocate (omptgt_field_t :: ptr)
    select type (ptr)
    type is (omptgt_field_t)
      call omptgt_field_init(self%ngrid, next, id=self%next_id, f=ptr)
    class default
      error stop "Allocation failed to set type"
    end select

  end function create_block_omptgt

  ! Constructs a device-resident field
  subroutine omptgt_field_init(ngrid, next, id, f)
    integer, intent(in) :: ngrid
    class(field_t), pointer, intent(in) :: next
    integer, intent(in) :: id
    type(omptgt_field_t) :: f

    f%refcount = 0
    f%next => next
    f%id = id

    f%dev_id = omp_get_default_device()
    if (f%dev_id == omp_get_initial_device()) then
      error stop "Device ID is HOST"
    end if

    f%dev_ptr = omp_target_alloc(ngrid*c_sizeof(0.0_dp), f%dev_id)
    call c_f_pointer(f%dev_ptr, f%p_data_tgt, shape=[ngrid])

  end subroutine omptgt_field_init

  subroutine omptgt_field_destroy(self)
    type(omptgt_field_t) :: self

    nullify (self%data_tgt)
    nullify (self%p_data_tgt)

    if (c_associated(self%dev_ptr)) then
      call omp_target_free(self%dev_ptr, self%dev_id)
    end if
  end subroutine

  subroutine fill_omptgt(self, c)
    class(omptgt_field_t) :: self
    real(dp), intent(in) :: c

    !call fill_omptgt_(self%p_data_tgt, c, size(self%p_data_tgt))
    call fill_omptgt_3d_(self%data_tgt, c)

  end subroutine fill_omptgt

  subroutine fill_omptgt_(p_data_tgt, c, n)
    real(dp), dimension(:), intent(inout) :: p_data_tgt
    real(dp), intent(in) :: c
    integer, intent(in) :: n

    integer :: i

    !$omp target teams loop has_device_addr(p_data_tgt)
    do i = 1, n
      p_data_tgt(i) = c
    end do
    !$omp end target teams loop

  end subroutine

  subroutine fill_omptgt_3d_(data_tgt, c)
    real(dp), dimension(:, :, :), intent(inout) :: data_tgt
    real(dp), intent(in) :: c

    integer, dimension(3) :: n
    integer :: i, j, k

    n = shape(data_tgt)

    !$omp target teams loop collapse(3) has_device_addr(data_tgt)
    do k = 1, n(3)
      do j = 1, n(2)
        do i = 1, n(1)
          data_tgt(i, j, k) = c
        end do
      end do
    end do
    !$omp end target teams loop
  end subroutine

  function get_shape_omptgt(self) result(dims)
    class(omptgt_field_t) :: self
    integer :: dims(3)

    dims = shape(self%data_tgt)
  end function

  subroutine set_shape_omptgt(self, dims)
    class(omptgt_field_t) :: self
    integer, intent(in) :: dims(3)

    call c_f_pointer(self%dev_ptr, self%data_tgt, shape=dims)

  end subroutine

end module m_omptgt_allocator