TABLE OF CONTENTS


ABINIT/m_profiling_abi [ Modules ]

[ Top ] [ Modules ]

NAME

 m_profiling_abi

FUNCTION

  This module is used for tracing memory allocations/deallocations
  when we compile the code with --enable-memory-profiling="yes" that, in turns, defines HAVE_MEM_PROFILE.

COPYRIGHT

 Copyright (C) 2010-2018 ABINIT group (MG)
 This file is distributed under the terms of the
 GNU General Public License, see ~abinit/COPYING
 or http://www.gnu.org/copyleft/gpl.txt .

NOTES

  *  This module is not thread-safe. However, this should not represent
     a significant limitation since memory-tracing is only enabled in debug mode.

m_abimem/abimem_abort [ Functions ]

[ Top ] [ Functions ]

NAME

  abimem_abort

FUNCTION

  Stop the code if an error occurs.

 INPUT
  msg=Error message
  file=File name
  func=Function name.
  line=Line number

PARENTS

CHILDREN

      date_and_time,mpi_abort

SOURCE

641 subroutine abimem_abort(msg, file, func, line)
642 
643 
644 !This section has been created automatically by the script Abilint (TD).
645 !Do not modify the following lines by hand.
646 #undef ABI_FUNC
647 #define ABI_FUNC 'abimem_abort'
648 !End of the abilint section
649 
650  implicit none
651 
652 !Arguments ------------------------------------
653  integer,intent(in) :: line
654  character(len=*),intent(in) :: msg,file,func
655 
656 !Local variables-------------------------------
657  integer :: ierr
658 
659 !Local variables-------------------------------
660  integer :: unt_found
661  logical :: isopen
662 ! *************************************************************************
663 
664  write(std_out,*)msg,file,func,line
665 
666  ! Close abimem_file if it's connected to flush io buffers and avoid file corruption
667  inquire(file=abimem_file, number=unt_found, opened=isopen)
668  if (isopen .and. (unt_found == logunt)) close(unit=logunt)
669 
670  ierr = 0
671 #ifdef HAVE_MPI
672  call MPI_ABORT(MPI_COMM_WORLD, MPI_ERR_UNKNOWN, ierr)
673 #endif
674  stop
675 
676 end subroutine abimem_abort

m_profiling_abi/abimem_basename [ Functions ]

[ Top ] [ m_profiling_abi ] [ Functions ]

NAME

 abimem_basename

FUNCTION

  Returns the final component of a pathname.

INPUTS

  string=The input string

NOTES

  * If the input string in not a valid path to a file (i.e not in the form foo/name)
    a blank strink is returned
  * We do a backward search becase we want to optimize the algorithm for Fortran strings.

SOURCE

698 pure function abimem_basename(string) result(basename)
699 
700 
701 !This section has been created automatically by the script Abilint (TD).
702 !Do not modify the following lines by hand.
703 #undef ABI_FUNC
704 #define ABI_FUNC 'abimem_basename'
705 !End of the abilint section
706 
707  character(len=*),intent(in) :: string
708  character(len=LEN_TRIM(string)) :: basename
709 
710 !Local variables-------------------------------
711  integer :: ic,nch_trim,nch
712  character(len=1),parameter :: DIR_SEPARATOR = '/'
713  character(len=1),parameter :: BLANK=' '
714 !************************************************************************
715 
716  nch     =LEN     (string)
717  nch_trim=LEN_TRIM(string)
718 
719  ic = INDEX (TRIM(string), DIR_SEPARATOR, back=.TRUE.)
720  !write(*,*)'DEBUG ',TRIM(string),ic
721 
722  if (ic >= 1 .and. ic <= nch_trim-1) then ! there is stuff after the separator.
723    basename = string(ic+1:nch_trim)
724    return
725  else if (ic==0 .or. ic == nch_trim+1) then ! no separator in string or zero length string,
726    basename = TRIM(string)                   ! return trimmed string.
727    return
728  else              ! (ic == nch_trim) separator is the last char.
729    basename= BLANK  ! This is not a valid path to a file, return blank.
730    return
731  end if
732 
733 end function abimem_basename

m_profiling_abi/abimem_check [ Functions ]

[ Top ] [ m_profiling_abi ] [ Functions ]

NAME

 abimem_check

FUNCTION

   Check the abimem.mocc file (verbose format)

PARENTS

      m_profiling_abi

CHILDREN

      date_and_time,mpi_abort

SOURCE

594 subroutine abimem_check(nalloc, ndealloc)
595 
596 
597 !This section has been created automatically by the script Abilint (TD).
598 !Do not modify the following lines by hand.
599 #undef ABI_FUNC
600 #define ABI_FUNC 'abimem_check'
601 !End of the abilint section
602 
603  implicit none
604 
605 !Arguments ------------------------------------
606  integer, intent(in) :: nalloc,ndealloc
607 ! *************************************************************************
608 
609  if (abimem_level==2 .and. nalloc /= ndealloc) then
610    write(std_out,"(3a)")"Use the python script 'abimem.py' in ~abinit/tests/scripts to check ",trim(abimem_file)," file"
611    write(std_out,"(a)")"Note that one can use the command line option `abinit --abimem-level=2"
612  end if
613 
614 end subroutine abimem_check

m_profiling_abi/abimem_get_info [ Functions ]

[ Top ] [ m_profiling_abi ] [ Functions ]

NAME

 abimem_get_info

FUNCTION

  Function that returns the number of allocations and deallocations that have
  been done and the memory currently used

OUTPUT

  nalloc       number of allocations that have been done
  ndealloc     number of deallocations that have been done
  allocmemory  total memory used

m_profiling_abi/abimem_init [ Functions ]

[ Top ] [ m_profiling_abi ] [ Functions ]

NAME

 abimem_init

FUNCTION

 INPUT
  level = Integer selecting the operation mode:
       0 no file abimem.mocc is created, only memory allocation counters running
       1 file abimem.mocc is created in a light version (only current information is written)
       2 file abimem.mocc is created with full information inside (default state if not specified)
       The status can only be downgraded. A stop signal is produced if status is increased
  [deltat]
  [filename] = If present, activate memory logging only inside filename.
  [funcname] = If present, activate memory logging only inside funcname.

m_profiling_abi/abimem_record [ Functions ]

[ Top ] [ m_profiling_abi ] [ Functions ]

NAME

 abimem_record

FUNCTION

  Control the memory occupation by calculating the overall size of the allocated arrays

  At the end of the calculation a short report is printed on the screen,
  some information can be also written on disk following the needs

  The file abimem.mocc is not deleted if the final total memory is not equal to zero.
  abimem_debug (parameter)
    == .true.  verbose format (useful with tests/scripts/abimem.py)
               then display a line per allocation or deallocation
               a routine at the end parses the file
    == .false. compact format

PARENTS

      abinit,aim,anaddb,band2eps,conducti,cut3d,dummy_tests,fftprof
      fold2Bloch,ioprof,lapackprof,macroave,mrgddb,mrgdv,mrggkk,mrgscr
      multibinit,optic,ujdet,vdw_kernelgen

CHILDREN

      date_and_time,mpi_abort

SOURCE

444 subroutine abimem_record(istat, vname, addr, act, isize, file, func, line)
445 
446 
447 !This section has been created automatically by the script Abilint (TD).
448 !Do not modify the following lines by hand.
449 #undef ABI_FUNC
450 #define ABI_FUNC 'abimem_record'
451 !End of the abilint section
452 
453  implicit none
454 
455 !Arguments ------------------------------------
456  integer, intent(in) :: istat,line
457  integer(kind=8), intent(in) :: isize,addr
458  character(len=*), intent(in) :: vname,act,file,func
459 
460 !Local variables-------------------------------
461  integer :: ierr
462  real(dp) :: now
463  logical :: do_log
464  character(len=500) :: msg
465 ! *************************************************************************
466 
467  ! Handle allocate/deallocate failures
468  !if (istat /= 0) then
469  !  write(msg,('(5a,i0,/,2a,/,a,i0,a)'))&
470  !   'Procedure: ',trim(funcname),"@",trim(filename),":",line,&
471  !   'problem of allocation of variable: ',trim(arr_name),&
472  !   'Error code = ',istat,' Aborting now...'
473  !  call abimem_abort(istat, msg, filename, funcname, line)
474  ! end if
475 
476  !control of the allocation/deallocation status
477  if (istat /= 0) then
478    if (isize >= 0) then
479      write(msg,*)&
480        trim(func),': problem of allocation of variable ',trim(vname),', error code= ',istat
481      _ABORT(msg)
482    else if (isize<0) then
483      write(msg,*)&
484        trim(func),': problem of deallocation of variable ',trim(vname),', error code= ',istat
485      _ABORT(msg)
486    end if
487  end if
488 
489  ! total counter, for all the processes
490  memtot_abi%memory = memtot_abi%memory + isize
491  if (memtot_abi%memory > memtot_abi%peak) then
492    memtot_abi%peak = memtot_abi%memory
493    memtot_abi%func = func
494    memtot_abi%vname = vname
495  end if
496 
497  if (isize > 0) then
498    num_alloc = num_alloc + 1
499  else if (isize < 0) then
500    num_free = num_free + 1
501  end if
502 
503  ! This is the correct check but tests fail!
504  !if (act == "A") then
505  !  num_alloc = num_alloc + 1
506  !else if (act == "D") then
507  !  num_free = num_free + 1
508  !else
509  !  _ABORT("Wrong action: "//trim(act))
510  !end if
511 
512  ! Check on memory limit.
513  if (abimem_limit /= zero .and. memtot_abi%memory > int(real(abimem_limit,kind=8)*1073741824.d0,kind=8)) then
514    ! memory limit is in GB
515    write(msg,'(a,f7.3,2(a,i0),a,2(a,i0))')&
516      'Memory limit of ',abimem_limit,' GB reached for rank ',my_rank,', total memory is ',memtot_abi%memory,' B.',&
517      'this happened for variable '//trim(memtot_abi%vname)//' in func '//trim(memtot_abi%func)
518    _ABORT(msg)
519  end if
520 
521  ! Selective memory tracing
522  do_log = .True.
523  if (select_file /= NONE_STRING) do_log = (select_file == file)
524  if (select_func /= NONE_STRING) do_log = do_log .and. (select_func == func)
525  !do_log = (do_log .and. my_rank == 0)
526 
527  ! Snapshot
528  if (do_log .and. last_snapshot >= zero) then
529    now = abimem_wtime()
530    if ((now - last_snapshot) >= dt_snapshot) then
531       last_snapshot = now
532    else
533       do_log = .False.
534    end if
535  end if
536 
537  if (do_log) then
538    select case (abimem_level)
539    case (0)
540      ! No action required
541 
542    case (1)
543      ! Compact format
544      if (trim(memloc_abi%func) /= func) then
545        if (memloc_abi%memory /= int(0,kind=8)) then
546          rewind(logunt)
547          write(logunt,'(a,t60,a,t90,4(1x,i12))')&
548            trim(memloc_abi%func),trim(memloc_abi%vname),&
549            memloc_abi%memory/int(1024,kind=8),memloc_abi%peak/int(1024,kind=8),&
550            memtot_abi%memory/int(1024,kind=8),&
551            (memtot_abi%memory+memloc_abi%peak-memloc_abi%memory)/int(1024,kind=8)
552        end if
553        memloc_abi%func = func
554        memloc_abi%vname = vname
555        memloc_abi%memory = isize
556        memloc_abi%peak = isize
557 
558      else
559        memloc_abi%memory=memloc_abi%memory+isize
560        if (memloc_abi%memory > memloc_abi%peak) then
561          memloc_abi%peak = memloc_abi%memory
562          memloc_abi%vname = vname
563        end if
564      end if
565 
566    case (2)
567      !to be used for inspecting a variable which is not deallocated
568      write(logunt,'(a,t60,a,1x,2(i0,1x),2(a,1x),2(i0,1x))')&
569        trim(vname), trim(act), addr, isize, trim(abimem_basename(file)), trim(func), line, memtot_abi%memory
570 
571    case default
572      _ABORT("invalid abimem_level")
573    end select
574  end if
575 
576 end subroutine abimem_record

m_profiling_abi/abimem_set_opts [ Functions ]

[ Top ] [ m_profiling_abi ] [ Functions ]

NAME

 abimem_set_opts

FUNCTION

 INPUT
  level = Integer selecting the operation mode:
       0 no file abimem.mocc is created, only memory allocation counters running
       1 file abimem.mocc is created in a light version (only current information is written)
       2 file abimem.mocc is created with full information inside (default state if not specified)
       The status can only be downgraded. A stop signal is produced if status is increased
  [limit]= Give a memory limit above which the code will stop properly. The unit is bytes.
  [filename] = If present, activate memory logging only inside filename.
  [funcname] = If present, activate memory logging only inside funcname.
  [deltat]

m_profiling_abi/abimem_shutdown [ Functions ]

[ Top ] [ m_profiling_abi ] [ Functions ]

NAME

 abimem_shutdowns

FUNCTION

 Perform final cleanup of the module and close files.

 INPUT

m_profiling_abi/abimem_t [ Types ]

[ Top ] [ m_profiling_abi ] [ Types ]

NAME

  minfo_t

FUNCTION

  Store information on the memory allocated at run-time

SOURCE

66  !Memory profiling
67  type :: abimem_t
68    integer(kind=8) :: memory = int(0, kind=8)
69    integer(kind=8) :: peak = int(0, kind=8)
70    character(len=slen) :: func = "_func"
71    character(len=slen) :: vname = "_vname"
72  end type abimem_t

m_time/abimem_wtime [ Functions ]

[ Top ] [ m_time ] [ Functions ]

NAME

  abimem_wtime

FUNCTION

  Return wall clock time in seconds since some arbitrary start.
  Call the F90 intrinsic date_and_time .

INPUTS

  (no inputs)

OUTPUT

  wall= wall clock time in seconds

PARENTS

CHILDREN

SOURCE

758 function abimem_wtime() result(wall)
759 
760 
761 !This section has been created automatically by the script Abilint (TD).
762 !Do not modify the following lines by hand.
763 #undef ABI_FUNC
764 #define ABI_FUNC 'abimem_wtime'
765 !End of the abilint section
766 
767  implicit none
768 
769 !Arguments ------------------------------------
770 !scalars
771  real(dp) :: wall
772 
773 !Local variables-------------------------------
774 !scalars
775 #ifndef HAVE_MPI
776  integer,parameter :: nday(24)=(/31,28,31,30,31,30,31,31,30,31,30,31,&
777 &                                31,28,31,30,31,30,31,31,30,31,30,31/)
778  integer,save :: month_init,month_now,start=1,year_init
779  integer :: months
780  character(len=8)   :: date
781  character(len=10)  :: time
782  character(len=5)   :: zone
783  character(len=500) :: msg
784 !arrays
785  integer :: values(8)
786 #endif
787 
788 ! *************************************************************************
789 
790 #ifndef HAVE_MPI
791 
792 !The following section of code is standard F90, but it is useful only if the intrinsics
793 !date_and_time is accurate at the 0.01 sec level, which is not the case for a P6 with the pghpf compiler ...
794 !Year and month initialisation
795  if(start==1)then
796    start=0
797    call date_and_time(date,time,zone,values)
798    year_init=values(1)
799    month_init=values(2)
800  end if
801 
802 !Uses intrinsic F90 subroutine Date_and_time for
803 !wall clock (not correct when a change of year happen)
804  call date_and_time(date,time,zone,values)
805 
806 !Compute first the number of seconds from the beginning of the month
807  wall=(values(3)*24.0d0+values(5))*3600.0d0+values(6)*60.0d0+values(7)+values(8)*0.001d0
808 
809 !If the month has changed, compute the number of seconds
810 !to be added. This fails if the program ran one year !!
811  month_now=values(2)
812  if(month_now/=month_init)then
813    if(year_init+1==values(1))then
814      month_now=month_now+12
815    end if
816    if(month_now<=month_init)then
817      msg = 'Problem with month and year numbers.'
818      _ABORT(msg)
819    end if
820    do months=month_init,month_now-1
821      wall=wall+86400.0d0*nday(months)
822    end do
823  end if
824 
825 !Now take into account bissextile years (I think 2000 is bissextile, but I am not sure ...)
826  if(mod(year_init,4)==0 .and. month_init<=2 .and. month_now>2)   wall=wall+3600.0d0
827  if(mod(values(1),4)==0 .and. month_init<=14 .and. month_now>14) wall=wall+3600.0d0
828 
829 #else
830 !Use the timer provided by MPI1.
831  wall = MPI_WTIME()
832 #endif
833 
834 end function abimem_wtime