Question

I am learning about how to port my FORTRAN source code to Openmp and came across a basic question regarding how to deal with threaded subroutines that contains global variables defined prior to the parallel region where the calling subroutines reside.

The following is an example code I made up for the question. I multiply a series of values from 1 to 1000000, named "a" by a global variable "p1." The multiplication is executed by a parallel-do hosting a subroutine that calls a function "afun" to do the element-wise multiplication a(i)*p1 and save respective result to corresponding b(i). The value of "p1" is assigned outside the parallel region, and thus a global variable to the subroutine "asub" and its called function "afun."

May I ask about what extra Openmp configuration I need to successfully run the program?

program common_test
    use omp_lib
    implicit none
    integer :: a(100000),b(100000)
    integer :: p1,i
    common /p_com/ p1
    !$omp threadprivate(/p_com/)
    do i=1,100000
        a(i)=i
    enddo
    p1=2
    !$omp parallel do shared(a,b) private(i) copyin(p1)
    do i=1,100000
        call asub(afun,i,b(i))
    enddo
    !$omp end parallel do
contains
    subroutine asub(func,x,y)
        implicit none
        interface
           function func(x,p)
           implicit none
           integer :: x,p,func
           end function func    
        end interface
        integer, intent(in) :: x
        integer, intent(out) :: y
        integer :: p1
        common /p_com/ p1
        y=func(x,p1)    
    end subroutine asub

    function afun(x,p)
        implicit none
        integer, intent(in) :: x
        integer :: p,afun
        afun=x*p
    end function afun
end program common_test
Was it helpful?

Solution

I finally got the example code run without receiving complaint from the Intel compiler. The correction I made is to replace copyin(p1) with copyin(/p_com/) at the end of the line of the second Openmp directive in the main program. That is,

program common_test
    use omp_lib
    implicit none
    integer :: a(100000),b(100000)
    integer :: p1,i
    common /p_com/ p1

    !$omp threadprivate(/p_com/)
    do i=1,100000
        a(i)=i
    enddo

    p1=2
    !$omp parallel do shared(a,b) private(i) copyin(/p_com/)
    do i=1,100000
        call asub(afun,i,b(i))
    enddo
    !$omp end parallel do
contains
    subroutine asub(func,x,y)
        implicit none
        interface
        function func(x,p)
        implicit none
        integer :: x,p,func
        end function func    
        end interface
        integer, intent(in) :: x
        integer, intent(out) :: y
        integer :: p1
        common /p_com/ p1
        y=func(x,p1)    
    end subroutine asub

    function afun(x,p)
        implicit none
        integer, intent(in) :: x
        integer :: p,afun
        afun=x*p
    end function afun
end program common_test
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top