MPI_REDUCE导致内存泄漏

4

我最近遇到了一种奇怪的行为。如果我在我的电脑上运行以下代码(使用最新版本的cygwin,Open MPI版本1.8.6),我会发现内存使用呈线性增长,很快就会超过我的电脑承受范围。

program memoryTest

use mpi

implicit none

integer            :: ierror,errorStatus      ! error codes
integer            :: my_rank                 ! rank of process
integer            :: p                       ! number of processes
integer            :: i,a,b

call MPI_Init(ierror)
call MPI_Comm_rank(MPI_COMM_WORLD, my_rank, ierror)
call MPI_Comm_size(MPI_COMM_WORLD, p, ierror)

b=0
do i=1,10000000
    a=1*my_rank
    call MPI_REDUCE(a,b,1,MPI_INTEGER,MPI_MAX,0,MPI_COMM_WORLD,errorStatus)
end do

call MPI_Finalize(ierror)

stop
end program memoryTest

有什么想法问题可能是什么?在我这个初学者的眼里,这段代码看起来很好。编译行为:

mpif90 -O2 -o memoryTest.exe memoryTest.f90

2
在提到Fortran时,应始终使用标签[tag:fortran]。如果出于某种原因需要区分版本,则可以使用[tag:fortran90]、[tag:fortran2003]或其他标签。 - Vladimir F Героям слава
可以在OpenSuSE Linux上确认。看起来像是一个库的问题。 - Vladimir F Героям слава
在 Gentoo Linux 上,使用 gcc-5.2.0 和 OpenMPI 1.10.0 可以重现此问题。 - casey
我很好奇 - 有人能确认这个问题在MPICH或Intel MPI中无法重现吗? - NoseKnowsAll
我可以使用mpich2 3.0.4和gfortran 4.9.3进行复现(意味着内存会爆炸)。然而,Intel MPI 5.1.1却像呼吸一样运行它。 - Gilles
2个回答

3

这个问题已经在相关线程这里讨论过了。

问题在于根进程需要从其他进程接收数据并执行归约,而其他进程只需要将数据发送到根进程。因此,根进程运行速度较慢,可能会被大量的传入消息压垮。如果在MPI_REDUCE调用后插入MPI_BARRIER调用,则代码应该可以正常运行。

MPI规范的相关部分说:“集体操作可以(但不一定)在参与者完成集体通信后立即完成。 阻塞操作在调用返回时就已经完成。非阻塞(即时)调用需要单独的完成调用(参见第3.7节)。集体操作的完成表示调用方可以自由修改通信缓冲区中的位置。它并不表示组中的其他进程已经完成或开始了操作(除非操作的描述另有说明)。因此,集体通信操作可能具有同步所有调用进程的效果,也可能没有。 当然,这个声明排除了屏障操作。”


1
为了对macelee的回答提供更多支持:如果在启用了MPICH内部内存泄漏跟踪/报告的情况下完成此程序,您将不会看到任何泄漏。此外,valgrind的泄漏检查报告。
==12866== HEAP SUMMARY:
==12866==     in use at exit: 0 bytes in 0 blocks
==12866==   total heap usage: 20,001,601 allocs, 20,000,496 frees, 3,369,410,210 bytes allocated
==12866== 
==12866== All heap blocks were freed -- no leaks are possible
==12866== 

Gcc的-fsanitize=leak则会显示许多泄漏,可能是虚警。至少对于OpenMPI(这是问题的目标,并非MPICH),我认为我也必须使用该标志编译MPI库。 - Vladimir F Героям слава
我发现MPICH的内部泄漏跟踪对于不仅是MPICH泄漏的东西,还包括用户忘记释放的东西非常有帮助,例如属性、数据类型、信息对象、文件句柄等等。我敢打赌OpenMPI也有类似的功能,但我对OpenMPI不太熟悉。 - Rob Latham
请注意,内存调试工具在MPI应用程序中的实用性可能会受到限制。为了获得更好的性能(这可能是实现MPI时的首要任务),开发人员可能会故意使用“不安全”的技术(例如将数据写入未初始化的内存)。事实上,根据其常见问题解答,OpenMPI并不支持Valgrind清理。 - macelee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接