How can I store private variables in routines called in a parallel openmp section?

I call the nested loop loop like this:

do ir = 1,Nr do iom = iom1, iom2 xyz(1) = xo(1) + xom(iom)*r xyz(2) = xo(2) + yom(iom)*r xyz(3) = xo(3) + zom(iom)*r call FUNSUB(xyz,Nprop,PropXYZ) enddo enddo 

where FUNSUB evaluates the property as follows:

 id = 1 do l=0,lmax do m=-l,l id = id + 1 Prop(id) = RHO * Ylm(l,m,xl(1),xl(2),xl(3)) enddo enddo 

now I'm trying to parallelize it with something like a form

 !$OMP parallel do reduction(+:Prop) private(ir, l, m, j, iom, r, wrad, xyz, PropOm, PropOm1, PropXYZ) 

where some other private variables visible here are left outside my sample code for brevity. I'm intentionally trying to make l and m confidential, so inside FUNSUB loops FUNSUB properties are evaluated independently. However, I find that they are shared between threads. I added some debugging options and found that id constantly goes beyond Prop and found that l also about lmax , and also m is outside of (-l,l) .

my question is: how can I make sure that l and m remain private and NOT separable from the main routine? it seems that the problem is that it is a completely different routine that contains these values โ€‹โ€‹and that somehow these private variable declarations are not portable

+4
source share
2 answers

I think your problem is that in Fortran, local subroutine variables can be static and that !$OMP does not apply to called functions.

Your code should work as expected if you copy-paste FUNSUB into the calling loops, i.e. if you manually nest it.

Update

After reading a little about how local variables may or may not be implemented by the compiler, I think your best option is to declare FUNSUB as RECURSIVE . This forces all local variables FUNSUB stack, which means that every OpenMP thread that calls FUNSUB will have its own, private set of local variables.

+3
source

The full FUNSUB code needs to be investigated. Proper use of an external function in the OpenMP area should not be a problem. There should be no reason, and it is impossible to declare variables in the volume of an external function as private.

Modern Fortran compilers will not create local variables for static functions unless you say so. This can be done using the compiler switch (a large value of NO NO in parallel code) or by declaring the variables as SAVE as it was saved. Note that all initialized SAVE variables are implicit. It means that:

  integer :: local = 0 

SAVE even without the keyword SAVE and will be shared between threads.

It is good practice to have all functions called in parallel declared as PURE . I am even for the fact that all non-recursive functions are equally effective PURE .

+1
source

All Articles