У меня следующий вопрос: как освободить память массива в типе? Как% b% c, как мне освободить c? конкретная проблема (среда компилятора, которую я пробовал, - это версия gfortran gcc4.4.7 и версия ifort 18.0.1.OS: linux):
module grist_domain_types
implicit none
public :: aaa
type bbb
real (8), allocatable :: c(:)
end type bbb
type aaa
type(bbb), allocatable :: b(:)
end type aaa
end module grist_domain_types
program main
use grist_domain_types
type(aaa) :: a
integer(4) :: time,i
time=20
allocate(a%b(1:100000000))
call sleep(time)!--------------1
do i=1,100000000
allocate(a%b(i)%c(1:1))
enddo
call sleep(time)!--------------2
do i=1,100000000
deallocate(a%b(i)%c)
enddo
call sleep(time)!--------------3
deallocate(a%b)
call sleep(time)!--------------4
end program
Сначала "gfortran main.F90 -o main" скомпилируйте программу и запустите эту программу. Затем я использую top -p processID, чтобы увидеть память. Когда программа выполняется до 1, объем памяти составляет 4,5 ГБ. Когда программа выполняется до 2, объем памяти составляет 7,5 ГБ. Когда программа выполняется до 3, память также составляет 7,5 ГБ (но я думаю, что это 4,5 ГБ). Когда программа выполняется до 4, память 3G (я думаю, 0G или близко к 0G). Итак, освобождение (a% b (i)% c), похоже, не работает. Однако я использую valgrind, чтобы увидеть память. память этой программы полностью освобождена ... Я использовал ifort и gfortran. Эта проблема возникает независимо от того, какой компилятор я использую. Как объяснить этот вопрос? Я выделяю много массивов c таким образом, программа окончательно выйдет из строя из-за нехватки памяти. И как это решить?
Взгляните на эта почта с форума Intel. Там есть 2 важные сведения:
(От доктора Форрана):
When you do a DEALLOCATE, the memory that was allocated returns to the pool used by the memory allocator (on Linux and OS X this is the same as C's malloc/free). The memory is not released back to the OS - it is very rare that this would even be possible. What often happens is that the pattern of allocations and deallocations causes virtual memory to be fragmented, so that while the total available space may be high, there may not be sufficient contiguous space to allocate a large item. Unlike with disks, there is no way to "defrag" memory.
(От Джима Демпси)
See if you can deallocate the memory in the reverse order in which it was allocated. This can reduce memory fragmentation.
Вы также можете обратиться к сообщению Intel этот другой:
During the program run, the Fortran runtime library will manage your heap. Yes, if data is DEALLOCATED, the runtime may choose to wait to release that memory. It's an optimization - if you do another ALLOCATE with the same size it will just reuse those pages. If the heap starts to run low, it will do some collection but not until it's absolutely necessary.
Кроме того, позвольте мне добавить кое-что: проверьте, нет ли других объектов, динамически создаваемых в области видимости, таких как автоматические массивы или копии временных массивов. Это может потребовать памяти, которая может быть освобождена только тогда, когда они выйдут из области видимости.
Подводя итоги, даже если "top" говорит, что память все еще используется, беспокоиться следует только в том случае, если ваша программа начинает давать сбой или если Valgrind показывает что-то ужасное.
Я видел проблему, которую они обсуждали. Это очень похоже на то, что я встречал. Может, они просто сказали причину. Не предложил решения. Так что я до сих пор не знаю, как это решить.
Дело в том, что, может быть, у вас нет проблем. У вас закончилась память? Память может быть недоступна для появляться, но если она была освобождена (помечена как свободная), но не освобождена, и программа запрашивает дополнительные выделения, эту память можно использовать повторно. Вы можете сделать другое распределение (после освобождения) и проверить, увеличилось ли использование памяти или было ли повторно использовано то же количество.
да, как вы догадались. проблема не в памяти. Мне нужно выделить таким образом много c-массивов? Он был освобожден, но не выпущен. Мне нужно, чтобы он был освобожден полностью. Я хочу, чтобы он был выпущен как обычный массив.
В итоге программа выйдет из строя из-за нехватки памяти.
@ L.Chao В этом случае предоставьте сбой MCVE, а не суррогат.
Я изменил вашу программу (чтобы посмотреть, где она была) и запустил Windows 7 / gFortran 7.2.0. Он не демонстрирует сохранение памяти, когда вы сообщаете, поскольку объем памяти возвращается к 13 МБ. Вопреки моему комментарию, потребность в памяти не изменилась во время инициализации c.
module grist_domain_types
implicit none
public :: aaa
type bbb
real (8), allocatable :: c(:)
end type bbb
type aaa
type(bbb), allocatable :: b(:)
end type aaa
end module grist_domain_types
program main
use grist_domain_types
type(aaa) :: a
integer(4),parameter :: million = 1000000
integer(4) :: n = 100*million
integer(4) :: time = 5, i, pass
do pass = 1,5
write (*,*) ' go #', pass
allocate(a%b(1:n))
write (*,*) 'allocate b'
call sleep(time)!--------------1
write (*,*) ' go'
do i=1,n
allocate(a%b(i)%c(1:1))
enddo
write (*,*) 'allocate c'
call sleep(time)!--------------2
write (*,*) ' go'
do i=1,n
a%b(i)%c = real(i)
enddo
write (*,*) 'use c'
call sleep(time)!--------------2a
write (*,*) ' go'
do i=1,n
deallocate(a%b(i)%c)
enddo
write (*,*) 'deallocate c'
call sleep(time)!--------------3
write (*,*) ' go'
deallocate(a%b)
write (*,*) 'deallocate b'
call sleep(time)!--------------4
end do
write (*,*) ' done : exit ?'
read (*,*) i
end program
edit: Я повторил тест с помощью do pass ... чтобы повторить требования к памяти. Это показывает отсутствие утечки памяти для этой программы Fortran. Я использую диспетчер задач для определения использования памяти как для этой программы, так и для операционной системы. Ваш конкретный компилятор O / S и Fortran может отличаться.
Я тоже не знаю, я просто новичок. Может быть, причина в том, что используемая вами версия компилятора отличается от моей.
В вашем тесте вы выделили память, но не использовали ее. Обычно (для массива) выделение резервирует память, но не может применяться к физической памяти. Я бы добавил операторы записи на каждом этапе, а также включил инициализацию c в цикл.