【问题标题】:Heap memory allocated but not free after calling MPI_TYPE_CREATE_STRUCT to create struct with allocatables调用 MPI_TYPE_CREATE_STRUCT 创建带有可分配对象的结构后,堆内存已分配但未释放
【发布时间】:2020-02-13 16:53:13
【问题描述】:

我正在尝试发送/接收带有可分配数组的派生数据类型。目前,我设法遵循了MPI derived datatype for dynamically allocated structs with dynamically allocated member 中的建议。这样,我的信息就正确传递了。但是,当我使用 tau 进行分析时,堆上分配的内存没有被释放并导致内存泄漏。

我已经通过注释打开/关闭不同的代码行进行了多次测试。只要我注释掉 MPI_TYPE_CREATE_STRUCT 函数,内存泄漏就会消失。

我也将帖子中的代码粘贴到我的代码中,但问题仍然存在。

我试过的编译器是openmpi-4.0.0、3.1.0和impi 18.0.2、18.0.0

这是我测试过的简单代码

这是内存泄漏版本

Program memory_leak

  implicit none
  include "mpif.h"
  TYPE Struct    
  INTEGER :: N
  DOUBLE PRECISION :: A
  DOUBLE PRECISION ,ALLOCATABLE :: B(:)
  END TYPE Struct
  TYPE(Struct) :: Structs(2)
  integer :: i
  integer :: Types(3)
  integer :: Blocks(3)
  integer :: Elem_Type(2), TwoElem_Type,IError
  integer(kind=MPI_ADDRESS_KIND) :: POS_(3)
  integer(kind=MPI_ADDRESS_KIND) :: Offsets(3)
  ALLOCATE(Structs(1)%B(10))
  ALLOCATE(Structs(2)%B(20))
  CALL MPI_INIT(IError)

  ! (1) Create a separate structure datatype for each record
  DO i=1,2
    CALL MPI_GET_ADDRESS(Structs(i)%N,    POS_(1), IError)
    CALL MPI_GET_ADDRESS(Structs(i)%A,    POS_(2), IError)
    CALL MPI_GET_ADDRESS(Structs(i)%B(1), POS_(3), IError)
    Offsets = POS_ - POS_(1)

    Types(1) = MPI_INTEGER
    Types(2) = MPI_DOUBLE_PRECISION
    Types(3) = MPI_DOUBLE_PRECISION

    Blocks(1) = 1
    Blocks(2) = 1
    Blocks(3) = i * 10

    CALL MPI_TYPE_CREATE_STRUCT(3, Blocks, Offsets, Types, Elem_Type(i), IError)
  END DO

  ! (2) Create a structure of structures that describes the whole array
  CALL MPI_GET_ADDRESS(Structs(1)%N, POS_(1), IError)
  CALL MPI_GET_ADDRESS(Structs(2)%N, POS_(2), IError)
  Offsets = POS_ - POS_(1)

  Types(1) = Elem_Type(1)
  Types(2) = Elem_Type(2)

  Blocks(1) = 1
  Blocks(2) = 1

  CALL MPI_TYPE_CREATE_STRUCT(2, Blocks, Offsets, Types, TwoElem_Type, IError)
  CALL MPI_TYPE_COMMIT(TwoElem_Type, IError)

  ! (2.1) Free the intermediate datatypes
  DO i=1,2
    CALL MPI_TYPE_FREE(Elem_Type(i), IError)
  END DO
  CALL MPI_TYPE_FREE(TwoElem_Type, IError)
  print *, "end"
  CALL MPI_FINALIZE(IError)

end program memory_leak

Memory leak using tau \

这是无泄漏版本

Program memory_leak

  implicit none
  include "mpif.h"
  TYPE Struct    
  INTEGER :: N
  DOUBLE PRECISION :: A
  DOUBLE PRECISION ,ALLOCATABLE :: B(:)
  END TYPE Struct
  TYPE(Struct) :: Structs(2)
  integer :: i
  integer :: Types(3)
  integer :: Blocks(3)
  integer :: Elem_Type(2), TwoElem_Type,IError
  integer(kind=MPI_ADDRESS_KIND) :: POS_(3)
  integer(kind=MPI_ADDRESS_KIND) :: Offsets(3)
  ALLOCATE(Structs(1)%B(10))
  ALLOCATE(Structs(2)%B(20))
  CALL MPI_INIT(IError)

  ! (1) Create a separate structure datatype for each record
  DO i=1,2
    CALL MPI_GET_ADDRESS(Structs(i)%N,    POS_(1), IError)
    CALL MPI_GET_ADDRESS(Structs(i)%A,    POS_(2), IError)
    CALL MPI_GET_ADDRESS(Structs(i)%B(1), POS_(3), IError)
    Offsets = POS_ - POS_(1)

    Types(1) = MPI_INTEGER
    Types(2) = MPI_DOUBLE_PRECISION
    Types(3) = MPI_DOUBLE_PRECISION

    Blocks(1) = 1
    Blocks(2) = 1
    Blocks(3) = i * 10

   ! CALL MPI_TYPE_CREATE_STRUCT(3, Blocks, Offsets, Types, Elem_Type(i), IError)
  END DO

  ! (2) Create a structure of structures that describes the whole array
  CALL MPI_GET_ADDRESS(Structs(1)%N, POS_(1), IError)
  CALL MPI_GET_ADDRESS(Structs(2)%N, POS_(2), IError)
  Offsets = POS_ - POS_(1)

  Types(1) = Elem_Type(1)
  Types(2) = Elem_Type(2)

  Blocks(1) = 1
  Blocks(2) = 1

  ! CALL MPI_TYPE_CREATE_STRUCT(2, Blocks, Offsets, Types, TwoElem_Type, IError)
  ! CALL MPI_TYPE_COMMIT(TwoElem_Type, IError)

  ! ! (2.1) Free the intermediate datatypes
  ! DO i=1,2
  !   CALL MPI_TYPE_FREE(Elem_Type(i), IError)
  ! END DO
  !CALL MPI_TYPE_FREE(TwoElem_Type, IError)
  print *, "end"
  CALL MPI_FINALIZE(IError)

end program memory_leak

【问题讨论】:

  • 两个程序完全相同!您也忘记在您的应用程序中DEALLOCATE(Structs(1)%B,Structs(2)%B)。如果问题仍然存在,请说明您使用的是哪个 MPI 库(供应商和版本)。
  • 嗨 Gilles,我更新了第二个。不同之处只是注释创建结构函数。这个问题,我认为与解除分配无关。尽管如此,我尝试添加该行,但它不起作用。我更新了我使用的版本,但我也会在这里说明它们,Openmpi 3.3 和 4.0,Intel mpi 18.0.2 和 18.0.0。都有内存泄漏问题
  • 没有 Open MPI 3.3 (3.0.3 ? 3.1.3?) 也没有 4.0 (4.0.0 ?)。 valgrind 没有向我报告任何泄漏。
  • 它的 3.1.0 和 4.0.0。对困惑感到抱歉。我在笔记本电脑上使用 valgrind 也没有发现任何泄漏。但是,当我在 HPC 上运行它并在 HPC 上运行 tau 时,发现泄漏并且内存使用率非常高且不合理
  • 这可能是一个但在 tau 中吗?

标签: fortran mpi


【解决方案1】:

解决了。问题出在代码的其他部分,我在可分配数组上使用了 pack 函数。当你使用pack时,数组会导致内存丢失,因为指针没有了但数组没有被释放

【讨论】:

    猜你喜欢
    • 2011-12-27
    • 2010-12-19
    • 2013-02-28
    • 2020-02-11
    • 1970-01-01
    • 2012-12-22
    • 1970-01-01
    • 2022-10-14
    • 2020-11-13
    相关资源
    最近更新 更多