2

It seems to me that fortran modules, which can be used to hold global variables across subroutines, don't work the same when using OpenMP. Here's an example:

main.f90

program main
   use mod
   implicit none
!$OMP PARALLEL private(a)
!$OMP DO
   do i=1,10
      a=i-1
      print*,"a =",a
      call echo
      print*,"b =",b
   enddo
!$OMP END DO
!$OMP END PARALLEL
end program main

echo.f90

subroutine echo
   use mod
   implicit none
   b=a+1
   !print *,a,"+1=",b
end subroutine echo

mod.f90

module mod
   integer:: i,a,b
end module mod

Now if you compile and run this without OpenMP you get:

a =           0
b =           1
a =           1
b =           2
a =           2

.....ect. This is what you'd expect

But, if you compile WITH openMP you get:

a =           7
b =           1
a =           6
b =           1
a =           8

.....ect. This is not what I want. I know that the echo subroutine is getting 'a' from the module, not the private 'a' that the thread has. Is there any way to do this besides passing it as an argument? There are a ton of variables in my module and it would be tedious.

1
  • what if you make echo returns or assigns b instead of sharing it since it is a elemental function depending only on a. I think several threads are modifying b at the same time. Commented Jan 7, 2015 at 18:40

1 Answer 1

10

Inside the procedure echo, a and b are variables that are referenced in a region but not in a construct - execution wise they appear in between a matching !$OMP PARALLEL and !$OMP END PARALLEL directive, but source wise they do not. As they are module variables, and in the absence of directives to the contrary, the rules for data sharing attributes in 2.14.1.2 of the OpemMP 4.0 standard specify that those variables inside the procedure are shared.

Consequently your example code has a data race, with multiple threads writing to b inside the echo subroutine without synchronization.

You can use the THREADPRIVATE directive in the module to change the data sharing attribute of those module variables. You will need to remove the private specification for a at the same time.

In the long run, a far better approach may be to make the flows of information in your program explicit to a reader of the code (and more flexibly configurable by a code writer), by passing information as arguments (perhaps bundled together in derived types) rather than hiding those flows through the use of global (module) variables.

Sign up to request clarification or add additional context in comments.

1 Comment

I'll accept this tomorrow when I try it. Unfortunately, I'm just an intern and I don't have permission to go ham on this code. I wasn't aware of THREADPRIVATE. Sounds like exactly what I need!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.