PSyclone icon indicating copy to clipboard operation
PSyclone copied to clipboard

Add support for the OpenMP If clause

Open sergisiso opened this issue 4 months ago • 0 comments

NEMO has some helper routines with loops that are called from multiple places in the call stack, for performance reasons I want to run them sometimes on the CPU and sometimes on the GPU, this is decided higher in the call chain.

One solution is using the OpenMP "if" clause with a global variable:

program test
    use omp_lib

    integer, parameter :: N = 1000
    real, dimension(N) :: data
    logical :: on_device = .true.
    
    call cpu_routine()
    call cpu_routine()
    call cpu_routine()
    call gpu_routine()
    call gpu_routine()
    call gpu_routine()
    
    contains
    
    subroutine gpu_routine()
        call helper()
    end subroutine gpu_routine
    
    subroutine cpu_routine()
        integer :: store_device

        ! Use the host device from here
        on_device = .false.
        
        call helper()

        ! Restore GPU device from here
        on_device = .true.
    end subroutine cpu_routine

    subroutine helper()
        integer :: i
        !$omp target if(on_device)
        !$omp loop
        do i = 1, N
            data(i) = i / 3.14
        end do
        !$omp end loop
        !$omp end target
    end subroutine helper
    
end program test

I also tried other approaches that don't need to create the global (e.g. setting and restoring the "omp_default_device"), because in reality the subroutines are in different translation units, but they didn't work - nvfortran does not create a host device that I can select dynamically. So unless somebody has an idea about how can I do the same without the global symbol, I will implement the if clause and put the global in a known location imported by all files.

sergisiso avatar Oct 23 '24 11:10 sergisiso