fortran取消分配数组,但未在OS中发布

时间:2018-07-09 03:31:35

标签: memory fortran dealloc

我有以下问题:如何取消分配类型的数组内存?像%b%c一样 我该如何分配c?具体的问题是(我尝试过的编译器环境是gfortran版本gcc4.4.7和ifort版本18.0.1.OS:linux):

repeat.for

首先,使用“ gfortran main.F90 -o main”来编译程序,然后运行该程序。然后,我使用top -p processID来查看内存。当程序执行到1时,内存为4.5G。当程序执行到2时,内存为7.5G。当程序执行到3时,内存也为7.5G(但我认为是4.5G)。当程序执行到4时,内存为3G(我认为是0G或接近0G)。因此,deallocate(a%b(i)%c)似乎不起作用。但是,我使用valgrind查看内存。该程序的内存全部是可释放的...我使用了ifort和gfortran。无论我使用哪个编译器,都会发生此问题。如何解释这个问题?我以这种方式分配了很多c数组,由于内存不足,程序最终将崩溃。以及如何解决?

2 个答案:

答案 0 :(得分:2)

在英特尔论坛上查看this post。其中有2条重要信息:

  1. (来自Forran医生):

      

    执行DEALLOCATE时,分配的内存将返回到内存分配器使用的池(在Linux和OS X上,这与C的malloc / free相同)。内存不会释放回操作系统-很少有这种可能性。经常发生的情况是,分配和释放模式会导致虚拟内存碎片化,因此尽管总可用空间可能很大,但可能没有足够的连续空间来分配大项目。与磁盘不同,无法对内存进行“碎片整理”。

  2. (来自Jim Dempsey)

      

    查看是否可以按照相反的顺序取消分配内存。这样可以减少内存碎片。

您也可以参考this other英特尔文章:

  

在程序运行期间,Fortran运行时库将管理您的堆。是的,如果已取消分配数据,则运行时可以选择等待释放该内存。这是一种优化-如果您执行另一个相同大小的ALLOCATE,它将仅重复使用这些页面。如果堆开始耗尽,它将进行一些收集,但是直到绝对必要时才进行收集。

此外,让我添加一些内容:检查是否在范围内没有动态创建其他对象,例如自动数组或临时数组副本。那可能是要求很高的内存,只有它们超出范围时才可以释放它们。

总结一下,即使'top'表示内存仍在使用中,您也应该开始担心,除非您的程序开始崩溃或Valgrind显示出一些麻烦。

答案 1 :(得分:0)

我修改了程序(以查看程序的运行位置),并在Windows 7 / gFortran 7.2.0上运行。报告中没有显示内存保留,因为内存恢复为13 mb。与我的评论相反,在初始化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:我给测试做了一次重复,通过...来重复内存需求。这表明此Fortran程序没有内存泄漏。我使用任务管理器来标识此程序和O / S的内存使用情况。您特定的操作系统和Fortran编译器可能有所不同。