I'm having a double free or corruption problem when trying to use the Reallocate function (from Fortran 90 Numerical Recipes) within an OpenMP parallel do directive
*** glibc detected *** ./myprog: double free or corruption (out): 0x00007ffdf7d770f0 ***
Here is the reallocate function :
FUNCTION reallocate_iv(p,n) INTEGER(I4B), DIMENSION(:), POINTER :: p, reallocate_iv INTEGER(I4B), INTENT(IN) :: n INTEGER(I4B) :: nold,ierr allocate(reallocate_iv(n),stat=ierr) if (ierr /= 0) call & nrerror('reallocate_iv: problem in attempt to allocate memory') if (.not. associated(p)) RETURN nold=size(p) reallocate_iv(1:min(nold,n))=p(1:min(nold,n)) deallocate(p) END FUNCTION reallocate_iv
and here is the main body of the code calling reallocate within an OpenMP parallel do directive :
Integer, Dimension(:), POINTER :: col_sprZ Integer :: nnz, size,spr_perc,spr_size !$OMP PARALLEL PRIVATE (size,spr_size,,col_sprZ,nnz) !$OMP DO SCHEDULE(DYNAMIC) do kk=1,NB spr_size = nint((spr_perc*9.*size**2.)/100.) Allocate(col_sprZ(spr_size)); !! here Call a Subroutine which calculates nnz and col_sprZ (sparse format storage) col_sprZ => Reallocate(col_sprZ,nnz); - - - - - - - - - - - - - Deallocate(col_sprZ); enddo !$OMP END DO !$OMP END PARALLEL
The code works perfectly and yields good results if I discard/comment the OpenMP directive or compile with the -O0 -openmp -heap arrays. It works also fine if I keep the openmp directive and compile with -O3 -openmp -heap arrays but use a classic temporary allocatable array to reallocate col_sprZ instead of the reallocate function.
I also noticed that the problem could disappear if I decrease the size of the array col_sprZ. I haven't the required authorization to check if the problem is caused by the stack size limits.
I am using intel composer 13.1.3 on Linux.
Did anyone understand or see the cause of this problem ? Thanks !
Prior to the parallel region, nullify col_sprZ
on the $omp parallel statement, identify col_sprZ as firstprivate (this is to copy in the NULLed pointer)
Following the Deallocate(col_sprZ), nullify col_sprZ
I cannot say that this will fix your problem (you have a rather old version of Fortran), the changes above make the program more conforming to the standard.
Thank your for taking the time to answer my question !
I tried what recommended and I got this :
forrtl: severe (174): SIGSEGV, segmentation fault occurred Image PC Routine Line Source myprog 00000000004BC379 nrutil_mp_realloc 219 nrutil.f90
The segmentation fault occurs from the beginning in the reallocate function here :
I checked nold and n and they correspond well to the initial/old size of p and the new size (nnz). So I don't really see what causes this segmentation fault. I increased the stack size limit : ulimit -s 2048 but I didn't change anything.
When I keep the nullify before and inside the parallel region, but I declare the pointer as PRIVATE and not FIRSTPRIVATE, I have
glibc detected *** ./myprog: munmap_chunk(): invalid pointer: 0x00002ae5e6b8bcc0
But the code runs longer, it seems to crash when leaving the do loop ! But I haven't any information about the line causing the problem. When I compile with -O3 -openmp -check all -traceback -heap-arrays, I of course loose the optimization (disabling optimization; runtime debug checks enabled) and the code runs perfectly and give accurate results ! so I haven't any further information about the 'munmap_chunk(): invalid pointer' problem.
Would you have any other suggestion ?
>>But the code runs longer, it seems to crash when leaving the do loop
Verify this by something like:
... !$OMP END DO print *,omp_get_thread_num() !$omp barrier !$omp master print *,"exiting region" !$omp end master !$OMP END PARALLEL print *,"out of region"
This may be a case where the problem lies with code not shown (- - - -).
Also as an aid:
!$OMP PARALLEL DEFAULT(NONE), PRIVATE (size,spr_size,,col_sprZ,nnz)
** then specifically add , SHARED(...) for those you know can be shared and won't be reallocated while running the parallel region.
I accidentally removed the subroutine, and when I modified a previous version very quickly, the code ran perfectly with the reallocate function the -O3 debug option and the OpenMP directive !!!
The only difference I noticed is a certain M=3*size inside the parallel region, which I used to avoid repeating 3*size each time I need it (see code below) ! I checked by using M=3*size again and the code crashes. I don't understand exactly what was the problem, since M is declared as private and used also later in the same do loop, but I think that NULLIFY did the biggest part of the job. Many thanks for your help !
Allocate(Zspr(spr_size),row_sprZ(3*size+1),col_sprZ(spr_size)); Call SR_Green_s_tr(size,Cells,spr_size,sameEps,nnz,Zspr,row_sprZ,col_sprZ) Zspr => reallocate(Zspr,nnz); col_sprZ => reallocate(col_sprZ,nnz); iparm3 = 0; ! here iparm3 is not used Call pardiso_solver(3*size,2*Nb,nnz,mtype,iparm3,row_sprZ,col_sprZ,Zspr,ER,E) Deallocate(Zspr,row_sprZ,col_sprZ); NULLIFY(Zspr,row_sprZ,col_sprZ);
>>The only difference I noticed is a certain M=3*size inside the parallel region, which I used to avoid repeating 3*size each time I need it
Perhaps M was unexpectedly modified after being set. Note: call Something(M,...) may potentially modify M whereas trashing the expression argument would do no harm.
Glad you are working.