Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28455 Discussions

Private variable are not correct when using OpenMP

siyuliben
Beginner
1,740 Views

Hi, 

I am using OpenMP to run a program.

I use 'MODULE' to define varibales. Within the omp do loop, subroutines are called and the variables are used in the subroutine. But when the private variables that are used in subroutine are not correct as what it was outside the subroutine.

I created a simple example. It is attached and shown below.

Integers 'icount' and 'abc' are not the same in the MAIN program and the SUBROUTINE called 'Mysubroutine'. However, the shared value 'sumcount' is correct.

 

module parm
integer :: icount
integer :: sumcount
integer :: abc
end module parm

 

program run
use parm
use omp_lib
implicit none

character(len=5) :: Name

sumcount=0
!$omp parallel
!$omp& shared ( sumcount )
!$omp& private ( icount, Name, abc )

!$omp do
do icount = 1, 2
write(*,*) icount
write(Name,'(I5.5)') icount
write(*,*) Name
abc = 123
sumcount = sumcount +1
call Mysubroutine(Name)

end do
!$omp end do

!$omp end parallel
end program run

subroutine Mysubroutine(Name)
use parm
use omp_lib
character(len=5) :: Name

write (*,*) Name
write (*,*) icount
write (*,*) sumcount
write (*,*) abc
end subroutine Mysubroutine

Labels (1)
0 Kudos
1 Solution
jimdempseyatthecove
Honored Contributor III
1,678 Views

In your program run, prior/subsequent to the parallel region with private(abc), the abc (should it be) referenced would be the abc of the module parm. This would also be the same abc of the module parm.

 

In your program run, the parallel region contains private(abc), thus a new instance of abc (same type) is created for each of the threads run within the parallel region (master thread can potential use the abc of the module parm).

 

Therefor you have an inconsistency with your stated use of private(abc) and your query for "How should I make both 'subroutine Mysubroutine' and 'program run' recognize 'abc' as the same variable?"

 

So I need to ask: Do you want a) all threads to share the same abc? Or, b) each thread to have unique abc (without passing abc as a dummy argument)?

if AND ONLY if b), then attribute abc in the module parm as THREADPRIVATE.

Jim Dempsey

View solution in original post

0 Kudos
5 Replies
jimdempseyatthecove
Honored Contributor III
1,714 Views

Some issues with your program

1) While abc is private in the omp parallel region in program run (same type as in the module parm but local to the parallel region), it is not the abc as used by subroutine Mysubroutine (which uses the module abc).

2) sumconunt, while shared is not atomically incremented. Thus, you may encounter a race condition between different threads perform: Read, Modify (increment), Write.

3) icount is a loop control variable which may or may not be registerized and thus you may be (likely are) reading a stale value.

Jim Dempsey

0 Kudos
siyuliben
Beginner
1,690 Views

Thank you Jim,

How should I make both 'subroutine Mysubroutine' and 'program run' recognize 'abc' as the same variable?

Thank you very much.

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,679 Views

In your program run, prior/subsequent to the parallel region with private(abc), the abc (should it be) referenced would be the abc of the module parm. This would also be the same abc of the module parm.

 

In your program run, the parallel region contains private(abc), thus a new instance of abc (same type) is created for each of the threads run within the parallel region (master thread can potential use the abc of the module parm).

 

Therefor you have an inconsistency with your stated use of private(abc) and your query for "How should I make both 'subroutine Mysubroutine' and 'program run' recognize 'abc' as the same variable?"

 

So I need to ask: Do you want a) all threads to share the same abc? Or, b) each thread to have unique abc (without passing abc as a dummy argument)?

if AND ONLY if b), then attribute abc in the module parm as THREADPRIVATE.

Jim Dempsey

0 Kudos
siyuliben
Beginner
1,666 Views

Thank you Jim,

I need each thread to have unique abc,


So I shouldn't set abc as private in program 'run', the module should be:

module parm
  integer :: icount
  integer :: sumcount
  integer :: abc
  !$OMP threadprivate(abc)
end module parm

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,659 Views

Yes on placement of threadprivate

Also use

    !$omp atomic update

    sumcount = sumcount + 1

 

to assure sumcount is updated correctly.

Jim Dempsey

0 Kudos
Reply