10
0
mirror of https://github.com/QuantumPackage/qp2.git synced 2024-11-09 07:33:49 +01:00
QuantumPackage/src/utils/memory.irp.f

165 lines
3.7 KiB
Fortran
Raw Normal View History

2019-01-25 11:39:31 +01:00
BEGIN_PROVIDER [ integer, qp_max_mem ]
implicit none
BEGIN_DOC
! Maximum memory in Gb
END_DOC
character*(128) :: env
2023-07-07 19:05:46 +02:00
integer, external :: get_total_available_memory
2019-01-25 11:39:31 +01:00
2023-07-07 19:05:46 +02:00
qp_max_mem = get_total_available_memory()
call write_int(6,qp_max_mem,'Total available memory (GB)')
2019-01-25 11:39:31 +01:00
call getenv('QP_MAXMEM',env)
if (trim(env) /= '') then
2023-04-17 17:03:16 +02:00
call lock_io()
2019-01-25 11:39:31 +01:00
read(env,*) qp_max_mem
2023-04-17 17:03:16 +02:00
call unlock_io()
2019-01-25 11:39:31 +01:00
endif
call write_int(6,qp_max_mem,'Target maximum memory (GB)')
END_PROVIDER
subroutine resident_memory(value)
2019-07-09 13:40:06 +02:00
use c_functions
2019-01-25 11:39:31 +01:00
implicit none
BEGIN_DOC
! Returns the current used memory in gigabytes used by the current process.
END_DOC
integer :: iunit
integer, external :: getUnitAndOpen
character*(32) :: key
double precision, intent(out) :: value
2023-04-17 17:03:16 +02:00
call lock_io()
2019-07-09 13:40:06 +02:00
call usleep(10)
2019-01-25 11:39:31 +01:00
value = 0.d0
2023-04-18 12:22:04 +02:00
IRP_IF MACOS
IRP_ELSE
2019-01-25 11:39:31 +01:00
iunit = getUnitAndOpen('/proc/self/status','r')
do
read(iunit,*,err=10,end=20) key, value
if (trim(key) == 'VmRSS:') then
exit
endif
10 continue
end do
20 continue
close(iunit)
2023-04-18 12:22:04 +02:00
IRP_ENDIF
2019-01-25 11:39:31 +01:00
value = value / (1024.d0*1024.d0)
2023-04-17 17:03:16 +02:00
call unlock_io()
2019-01-25 11:39:31 +01:00
end function
subroutine total_memory(value)
implicit none
BEGIN_DOC
! Returns the current used memory in gigabytes used by the current process.
END_DOC
integer :: iunit
integer, external :: getUnitAndOpen
character*(32) :: key
double precision, intent(out) :: value
2023-04-17 17:03:16 +02:00
call lock_io()
2023-04-18 12:22:04 +02:00
value = 0.d0
IRP_IF MACOS
IRP_ELSE
2019-01-25 11:39:31 +01:00
iunit = getUnitAndOpen('/proc/self/status','r')
do
read(iunit,*,err=10,end=20) key, value
if (trim(key) == 'VmSize:') then
exit
endif
10 continue
end do
20 continue
close(iunit)
2023-04-18 12:22:04 +02:00
IRP_ENDIF
2019-01-25 11:39:31 +01:00
value = value / (1024.d0*1024.d0)
2023-04-17 17:03:16 +02:00
call unlock_io()
2019-01-25 11:39:31 +01:00
end function
double precision function memory_of_double(n)
implicit none
BEGIN_DOC
! Computes the memory required for n double precision elements in gigabytes.
END_DOC
integer, intent(in) :: n
double precision, parameter :: f = 8.d0 / (1024.d0*1024.d0*1024.d0)
memory_of_double = dble(n) * f
end function
double precision function memory_of_int(n)
implicit none
BEGIN_DOC
! Computes the memory required for n double precision elements in gigabytes.
END_DOC
integer, intent(in) :: n
double precision, parameter :: f = 4.d0 / (1024.d0*1024.d0*1024.d0)
memory_of_int = dble(n) * f
end function
subroutine check_mem(rss_in,routine)
implicit none
BEGIN_DOC
! Checks if n gigabytes can be allocated. If not, exit the run.
END_DOC
double precision, intent(in) :: rss_in
character*(*) :: routine
2023-07-11 22:17:40 +02:00
double precision :: mem
call resident_memory(mem)
2023-07-11 22:17:40 +02:00
mem += rss_in
if (mem > qp_max_mem) then
call print_memory_usage()
2019-01-25 11:39:31 +01:00
print *, 'Not enough memory: aborting in ', routine
2023-07-11 22:17:40 +02:00
print *, mem, ' GB required'
2019-01-25 11:39:31 +01:00
stop -1
endif
end
subroutine print_memory_usage()
implicit none
BEGIN_DOC
! Prints the memory usage in the output
END_DOC
double precision :: rss, mem
call resident_memory(rss)
call total_memory(mem)
2022-03-09 10:23:27 +01:00
write(*,'(A,F14.3,A,F14.3,A)') &
2019-01-25 11:39:31 +01:00
'.. >>>>> [ RES MEM : ', rss , &
' GB ] [ VIRT MEM : ', mem, ' GB ] <<<<< ..'
end
2023-07-07 19:05:46 +02:00
integer function get_total_available_memory() result(res)
implicit none
BEGIN_DOC
! Returns the total available memory on the current machine
END_DOC
character(len=128) :: line
integer :: status
integer :: iunit
integer*8, parameter :: KB = 1024
integer*8, parameter :: GiB = 1024**3
integer, external :: getUnitAndOpen
iunit = getUnitAndOpen('/proc/meminfo','r')
res = 512
do
read(iunit, '(A)', END=10) line
if (line(1:10) == "MemTotal: ") then
read(line(11:), *, ERR=20) res
res = int((res*KB) / GiB,4)
exit
20 continue
end if
end do
10 continue
close(iunit)
end function get_total_available_memory