# Gfortran GPU offload with OpenMP

**URL:** <https://fortran-lang.discourse.group/t/gfortran-gpu-offload-with-openmp/314>\
**Category:** Help\
**Created:** [September 24, 2020, 4:23am UTC](https://fortran-lang.discourse.group/t/gfortran-gpu-offload-with-openmp/314 "2020-09-24T04:23:55Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![imorozov](https://avatars.discourse-cdn.com/v4/letter/i/4af34b/32.png) [@imorozov](https://fortran-lang.discourse.group/u/imorozov)\
**Post date:** [September 24, 2020, 4:23am UTC](https://fortran-lang.discourse.group/t/gfortran-gpu-offload-with-openmp/314/1 "2020-09-24T04:23:55Z")

</div>

Hi,

Do I understand correctly that `OpenMP` allows to offload computations to `GPU` and `gfortran` supports this?  
I’m looking for a minimal example of offloading a simple `!$OMP PARALLEL DO` construct to `GPU`.

Or, what can be used to generate `GPU` `FORTRAN` programs?  
I have some experience with `OpenACC` and `pgfortran` (no luck on `gfortran`).

---

<div class="post-metadata">

**Author:** ![vmagnin](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/vmagnin/32/28_2.png) [@vmagnin](https://fortran-lang.discourse.group/u/vmagnin)\
**Post date:** [September 24, 2020, 12:05pm UTC](https://fortran-lang.discourse.group/t/gfortran-gpu-offload-with-openmp/314/3 "2020-09-24T12:05:28Z")

</div>

> [@imorozov](#):
>
> Do I understand correctly that `OpenMP` allows to offload computations to `GPU` and `gfortran` supports this?

I didn’t know OpenMP could also be used on GPU.  
I have found that presentation:

> **[s8344-openmp-on-gpus-first-experiences-and-best-practices.pdf](https://on-demand.gputechconf.com/gtc/2018/presentation/s8344-openmp-on-gpus-first-experiences-and-best-practices.pdf)**
>
> 455.01 KB

---

<div class="post-metadata">

**Author:** ![JerryD](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/jerryd/32/393_2.png) [@JerryD](https://fortran-lang.discourse.group/u/JerryD)\
**Post date:** [September 25, 2020, 3:17am UTC](https://fortran-lang.discourse.group/t/gfortran-gpu-offload-with-openmp/314/4 "2020-09-25T03:17:21Z")

</div>

Use compiler flag -fopenmp to turn on this feature. Here is an example from the gcc/gfortran testsuite:

subroutine bar (i, j, k, s, a)  
integer :: i, j, k, s, a(100), l  
!$omp parallel do schedule (guided, s \* 2)  
do 100, l = j, k  
100 a(l) = i  
!$omp parallel do schedule (guided, s \* 2)  
do 101, l = j, k, 3  
101 a(l) = i + 1  
end subroutine bar

This is not the best example. Show us the simple loop(s) you want to parrallelize and we might be able to help you further.

---

<div class="post-metadata">

**Author:** ![imorozov](https://avatars.discourse-cdn.com/v4/letter/i/4af34b/32.png) [@imorozov](https://fortran-lang.discourse.group/u/imorozov)\
**Post date:** [September 26, 2020, 6:54am UTC](https://fortran-lang.discourse.group/t/gfortran-gpu-offload-with-openmp/314/5 "2020-09-26T06:54:55Z")

</div>

A simple OpenMP loop is not a problem, but I’m failing to find a good reference/example of OpenMP and GPU interaction. I’ve seen the presentation linked by @vmagnin, but didn’t manage to build working simple example.

Looks like `pgfortran` is now morphed into `nvfortran` and the code below can be executed on GPU with OpenACC, but it requires adding `!$acc routine` info to all procedures.

```auto
! OpenMP (cpu)
! gfortran -o test -fopenmp -O0 test.f90
! OpenACC (gpu)
! nvfortran -o test -acc -O0 -ta=nvidia test.f90
module data
  use, intrinsic :: iso_fortran_env, only : rk => real64
  implicit none
  integer, parameter :: loop = 10**6
  contains
  real(rk) function task(var)
    !$acc routine seq
    real(rk), intent(in) :: var
    integer :: i
    do i = 1, loop, 1
      task = exp(real(i,rk))
    end do
    task = var
  end function task
end module
program test
  use, intrinsic :: iso_fortran_env, only : rk => real64
  use data
  implicit none
  integer, parameter :: length = 2**10
  real(rk), dimension(length) :: input
  real(rk), dimension(length) :: output
  integer :: i
  input = real([(i, i=1,length,1)], rk)
  !$omp parallel do
  !$acc parallel loop copyin(input) copyout(output)
  do i = 1, length
    output(i) = task(input(i))
  end do
  !$acc end parallel loop
  !$omp end parallel do
  do i = 1, length
    write(*,*) output(i)
  end do
end program test

```

---

<div class="post-metadata">

**Author:** ![fluidnumerics\_joe](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/fluidnumerics_joe/32/4360_2.png) [@fluidnumerics\_joe](https://fortran-lang.discourse.group/u/fluidnumerics_joe)\
**Post date:** [October 1, 2020, 12:57pm UTC](https://fortran-lang.discourse.group/t/gfortran-gpu-offload-with-openmp/314/6 "2020-10-01T12:57:08Z")

</div>

Check out AMDs AOMP repository. The AOMP package provides clang and flang compilers that will handle GPU offloading. The repository also provides examples for both C and Fortran. In short, you’ll need to wrap your do loop with Target directives. Further, to distribute many GPU threads in parallel, you’ll want to use

!$OMP teams distribute parallel for

For example,

!$OMP target  
!$OMP teams distribute parallel for num\_threads(256)  
DO i = 1, N  
a(i) = b(i) + c(i)  
ENDDO

!$OMP end target

If you prefer to use gfortran, you’ll need to build the compiler from source. For Nvidia platforms, make sure you have CUDA toolkit installed before building. For AMD, have rocm-dev installed. I’ve haven’t built gfortran for OpenMP offloading since v8, but it looks like GNU has some guidance on this :

> **[Offloading - GCC Wiki](https://gcc.gnu.org/wiki/Offloading)**

---

<div class="post-metadata">

**Author:** ![fortran4r](https://avatars.discourse-cdn.com/v4/letter/f/9de0a6/32.png) [@fortran4r](https://fortran-lang.discourse.group/u/fortran4r)\
**Post date:** [November 26, 2022, 2:29pm UTC](https://fortran-lang.discourse.group/t/gfortran-gpu-offload-with-openmp/314/7 "2022-11-26T14:29:26Z")

</div>

Any updates on this? I got a new version (12.2.1) of GFortran today.

---

<div class="post-metadata">

**Author:** ![fluidnumerics\_joe](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/fluidnumerics_joe/32/4360_2.png) [@fluidnumerics\_joe](https://fortran-lang.discourse.group/u/fluidnumerics_joe)\
**Post date:** [August 23, 2023, 8:42pm UTC](https://fortran-lang.discourse.group/t/gfortran-gpu-offload-with-openmp/314/8 "2023-08-23T20:42:27Z")

</div>

Better late than never, I suppose… With GNU compilers, you will need to build them with offloading support : [Offloading - GCC Wiki](https://gcc.gnu.org/wiki/Offloading#How_to_build_an_offloading-enabled_GCC)

I haven’t tried it yet, but you may be able to install GNU compilers with OpenMP (and OpenACC offloading) to Nvidia GPUs using the `+nvptx` variant, e.g.

```auto
spack install gcc@12.3.0 +nvptx

```
