【发布时间】: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
这是无泄漏版本
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 中吗?