gpt4 book ai didi

fortran90 - 在 fortran 90 中使用标准数组和派生类型时的内存使用差异

转载 作者:行者123 更新时间:2023-12-05 00:31:31 24 4
gpt4 key购买 nike

我观察到有关派生数据类型的内存使用情况的奇怪行为。以下 fortran90 代码演示了该问题。

  module prec
implicit none
integer, parameter :: d_t = selected_real_kind(15,307)
end module
module typdef
use prec
implicit none
type level_2
real(kind=d_t), allocatable :: lev_3(:)
end type
type level_1
type(level_2),allocatable :: lev_2(:,:)
end type
type array
type(level_1),allocatable :: lev_1(:,:)
end type
end module
program mem_test
use prec
use typdef
implicit none
integer :: n,i,j,k,l,m,egmax,niter,ncells,namom,nsmom
real(kind=d_t),allocatable :: simple_array(:,:,:,:,:)
type(array) :: fancy_array
real(kind=d_t) :: it
egmax=7
niter=2
ncells=3000000
namom=1
nsmom=1
!
!
!
allocate( simple_array(egmax,niter,ncells,namom,nsmom) )
!
!
!
allocate( fancy_array%lev_1(egmax,niter))
do i=1,niter
do j=1,egmax
allocate( fancy_array%lev_1(j,i)%lev_2(ncells,namom) )
end do
end do
do i=1,niter
do j=1,egmax
do k=1,namom
do l=1,ncells
allocate( fancy_array%lev_1(j,i)%lev_2(l,k)%lev_3(nsmom) )
end do
end do
end do
end do
!
do n=1,100000
it=0.0_d_T
do i=1,100000
it=it+1.0_d_t
end do
end do
!
!
deallocate(simple_array)
deallocate(fancy_array%lev_1)
end program

我想将数据存储在多维数组中(例如max*niter*ncell*namom*nsmom double 数)。我以两种不同的方式做到了这一点:
  • 多维标准数组“simple_array(egmax,niter,...,)”
  • 我提供的一段代码中定义的嵌套派生数据结构“fancy_array”。

  • 我使用编译代码
        ifort -g -o  test.exe file.f90

    我在 valgrind 中运行它并比较了 simple_array 和fancy_array 的内存消耗。 simple_array 按预期使用大约 300Mb 而fancy_array 使用 3Gb(10 倍),即使它存储
    相同数量的实数。因此,它也应该只消耗 300Mb。

    运行一个更简单的测试用例,其中派生类型只有一层深,例如
         type level_1
    real(kind=d_t),allocatable :: subarray(:)
    end type
    type array
    type(level_1),allocatable :: lev_1(:)
    end type

    消耗的内存量正是我期望的。它不会消耗 10 倍
    内存。有没有人观察到类似的行为或有任何线索为什么会发生这种情况?对于所描述的行为,我唯一的想法是fancy_array 分配了非连续内存,而fortran 需要以某种方式跟踪它,因此内存消耗增加。我将不胜感激任何输入或类似的意见。

    谢谢你的帮助。

    塞巴斯蒂安

    最佳答案

    (可分配组件是 Fortran 2003 的一项功能。)

    Fortran 处理器(包括 Intel Fortran)实现可分配数组对象的典型方法是使用描述符 - 一种数据结构,其中包含诸如数组数据在内存中的位置以及数组每个维度的边界和步幅等信息, amongst other things .

    对于 x64 平台上的 Intel Fortran,该描述符占用 72 字节的一维可分配数组。在您的派生类型案例中,您有大约 4200 万个这样的数组 - 每个 lev_3 一个。您引入的组件,加上父可分配组件的数量要少得多。 72 字节乘以 4200 万字节大约为 3 GB。可能存在与底层内存分配器相关联的更多开销。

    在同一平台上,五阶数组的描述符占用 168 字节,并且只有一个内存分配

    这两种方法的数据存储要求大致相同。

    请注意,两种方法提供的功能显着不同(因此开销不同) - 在派生类型的情况下,您可以更改每个 lev_3 的分配状态、边界和范围。成分。在单个数组的情况下,您没有任何接近这种灵活性的地方 - 如果分配该数组必须是矩形。

    (在 Fortran 90 中,声明中组件的维度需要是常量表达式(在编译时固定)。不会使用描述符,两种方法的内存需求会收敛。)

    关于fortran90 - 在 fortran 90 中使用标准数组和派生类型时的内存使用差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14543075/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com