I am trying to allocate a field that is part of an abstract data type within an OpenMP parallel region. To do the job I am calling an initialization subroutine defined in the same module. I encounter the following behavior:
- if the variable is declared private then the field appears to be allocated both inside the module and after the call to the initialization subroutine in the main program
- if the variable is declared shared the field is allocated within the module, but IS NOT allocated after the call to the initialization subroutine in the main program
I am quite a newbie of OpenMP so I was wondering if this is the behavior I should expect. In this case how I can initialize a shared variable of this kind?
Anyhow: I did try to use the "flush" directive already, and that does not seem to work in my case. Furthermore I found in:
that the flush directive should be implied after an "end single" directive, and this also does not seem to be the case for me.
Just to be clear I attach a modified version of the simple example provided above with "flush" inserted:
[bash]program main use dummy use omp_lib type(pippo) :: struct,pstruct integer :: tid,nthreads real(8), allocatable :: vect(:) !$omp parallel default(shared) private(tid,ntrheads,pstruct) tid = omp_get_thread_num() nthreads = omp_get_num_threads() !$omp critical print *,tid,nthreads call initstruct(pstruct) !$omp end critical !$omp barrier !$omp flush(struct,pstruct) !$omp single print * call initstruct(struct ) call initvec(vect) !$omp flush(struct,pstruct) print * print *,allocated(struct%vec),tid,nthreads print *,allocated(vect),tid,nthreads print * if (allocated(struct%vec)) then call freestruct(struct) end if if (allocated(vect)) then deallocate(vect) end if !$omp end single !$omp flush(struct) print *,allocated(struct%vec),tid,nthreads print *,allocated(pstruct%vec),tid,nthreads if (allocated(pstruct%vec)) then call freestruct(pstruct) end if !$omp end parallel end program main[/bash]
these are the instructions I use to compile the code:
- ifort -c dummy.f90 -module ./
- ifort -o 03-allocatable.bin -openmp 03-allocatable.f90 *.o -module ./
F 0 3
T 0 3
F 2 3
T 2 3
F 0 3
T 0 3
F 1 3
T 1 3
Furthermore this is the output of valgrind at the end of the procedure:
==4682== LEAK SUMMARY:
==4682== definitely lost: 80 bytes in 1 blocks
==4682== indirectly lost: 0 bytes in 0 blocks
==4682== possibly lost: 416 bytes in 2 blocks
==4682== still reachable: 20 bytes in 1 blocks
==4682== suppressed: 0 bytes in 0 blocks
==4682== Reachable blocks (those to which a pointer was found) are not shown.
==4682== To see them, rerun with: --leak-check=full --show-reachable=yes
Some part of memory appears to be lost, and I my impression is that it is possibly the shared abstract data-type.
Any clue to shed some light on this behavior?
Add barrier following end of single.
The threads not taking single path are performing print prior to allocation by thread in single.
Just a quick question: isn't a barrier already implied by an "end single" directive?
!$omp single default(shared)
If for some reason !$omp single is using (creating)private copies, then you would see this behavior.
I do not know about your second question (IOW consult the documentation). I suppose if it did, you could add nowait to permit non-barrier usage.
The point of trying !$omp single default(shared) was to investigate why the allocation appeared to be private within the scope of the single. Your next step is to determine if indeed the array descriptor is private or shared. For this you may need to insert a subroutine call to a C++ routine that passes an assumed shape array (descriptor), then simply print out the address of the array descriptor.
If the array discriptor is shared, then the problem lies in deallocation of what is thought to be an autoallocated array or subroutine local allocated array, which in newer fortran is autodeallocated. Note, allocation to (dummy arg) pointershould not be auto-deallocated