module procedures use iso_c_binding, only: c_ptr, c_f_pointer use omp_lib implicit none contains function foo(bv, av, n) result(res) implicit none integer :: res, n, i type(c_ptr) :: bv type(c_ptr) :: av real(8), pointer :: fp_bv(:), fp_av(:) ! Fortran pointers for array access !$omp declare variant(bar) match(construct={dispatch}) adjust_args(need_device_ptr: bv, av) !$omp declare variant(baz) match(implementation={vendor(gnu)}) ! Associate C pointers with Fortran pointers call c_f_pointer(bv, fp_bv, [n]) call c_f_pointer(av, fp_av, [n]) ! Perform operations using Fortran pointers do i = 1, n fp_bv(i) = fp_av(i) * i end do res = -1 end function foo function baz(d_bv, d_av, n) result(res) implicit none integer :: res, n, i type(c_ptr) :: d_bv type(c_ptr) :: d_av real(8), pointer :: fp_bv(:), fp_av(:) ! Fortran pointers for array access ! Associate C pointers with Fortran pointers call c_f_pointer(d_bv, fp_bv, [n]) call c_f_pointer(d_av, fp_av, [n]) !$omp distribute parallel do do i = 1, n fp_bv(i) = fp_av(i) * i end do res = -3 end function baz function bar(d_bv, d_av, n) result(res) implicit none integer :: res, n, i type(c_ptr) :: d_bv type(c_ptr) :: d_av !$omp target is_device_ptr(d_bv, d_av) block real(8), pointer :: fp_bv(:), fp_av(:) ! Fortran pointers for array access ! Associate C pointers with Fortran pointers call c_f_pointer(d_bv, fp_bv, [n]) call c_f_pointer(d_av, fp_av, [n]) ! Perform operations on target do i = 1, n fp_bv(i) = fp_av(i) * i end do end block res = -2 end function bar function test(n) result(res) use iso_c_binding, only: c_ptr, c_loc implicit none integer :: n, res, i, f, ff, last_dev real(8), allocatable, target :: av(:), bv(:), d_bv(:) real(8), parameter :: e = 2.71828d0 type(c_ptr) :: c_av, c_bv, c_d_bv allocate(av(n), bv(n), d_bv(n)) ! Initialize arrays do i = 1, n av(i) = e * i bv(i) = 0.0d0 d_bv(i) = 0.0d0 end do last_dev = omp_get_num_devices() - 1 c_av = c_loc(av) c_d_bv = c_loc(d_bv) !$omp target data map(to: av(:n)) map(from: d_bv(:n)) device(last_dev) if(n == 1024) !$omp dispatch nocontext(n > 1024) novariants(n < 1024) device(last_dev) f = foo(c_d_bv, c_av, n) !$omp end target data c_bv = c_loc(bv) ff = foo(c_bv, c_loc(av), n) ! Verify results do i = 1, n if (d_bv(i) /= bv(i)) then write(0,*) 'ERROR at ', i, ': ', d_bv(i), ' (act) != ', bv(i), ' (exp)' res = 1 return end if end do res = f deallocate(av, bv, d_bv) end function test end module procedures program main use procedures implicit none integer :: ret ret = test(1023) if (ret /= -1) stop 1 ret = test(1024) if (ret /= -2) stop 1 ret = test(1025) if (ret /= -3) stop 1 end program main