在大量内核上调试我的程序时,我遇到了非常奇怪的错误insufficient virtual memory
。我的调查导致了代码的和平,主站向每个从站发送小消息。然后我写了一个小程序,其中 1 个 master 只需发送 10 个整数MPI_SEND
所有奴隶都会收到它MPI_RECV
。文件比较/proc/self/status
之前和之后MPI_SEND
结果表明,内存大小之间的差异是巨大的!最有趣的事情(这使我的程序崩溃)是,该内存在之后不会释放MPI_Send
并且仍然占用巨大的空间。
有任何想法吗?
System memory usage before MPI_Send, rank: 0
Name: test_send_size
State: R (running)
Pid: 7825
Groups: 2840
VmPeak: 251400 kB
VmSize: 186628 kB
VmLck: 72 kB
VmHWM: 4068 kB
VmRSS: 4068 kB
VmData: 71076 kB
VmStk: 92 kB
VmExe: 604 kB
VmLib: 6588 kB
VmPTE: 148 kB
VmSwap: 0 kB
Threads: 3
System memory usage after MPI_Send, rank 0
Name: test_send_size
State: R (running)
Pid: 7825
Groups: 2840
VmPeak: 456880 kB
VmSize: 456872 kB
VmLck: 257884 kB
VmHWM: 274612 kB
VmRSS: 274612 kB
VmData: 341320 kB
VmStk: 92 kB
VmExe: 604 kB
VmLib: 6588 kB
VmPTE: 676 kB
VmSwap: 0 kB
Threads: 3
这是几乎所有在 InfiniBand 上运行的 MPI 实现的预期行为。 IB RDMA 机制要求数据缓冲区应该被注册,即它们首先被锁定到物理内存中的固定位置,然后驱动程序告诉 InfiniBand HCA 如何将虚拟地址映射到物理内存。它非常复杂,因此非常slow注册内存以供 IB HCA 使用的过程,这就是为什么大多数 MPI 实现从不取消注册曾经注册过的内存,以期以后再次将同一内存用作源或数据目标。如果注册的内存是堆内存,它永远不会返回到操作系统,这就是数据段大小只会增长的原因。
尽可能重用发送和接收缓冲区。请记住,通过 InfiniBand 进行通信会产生较高的内存开销。大多数人并没有真正考虑到这一点,而且通常记录很少,但是 InfiniBand 使用了许多特殊的数据结构(队列),这些数据结构分配在进程的内存中,并且这些队列随着进程数量的增加而显着增长。在某些完全连接的情况下,队列内存量可能非常大,以至于实际上没有为应用程序留下任何内存。
有一些参数可以控制英特尔 MPI 使用的 IB 队列。在你的情况下最重要的是I_MPI_DAPL_BUFFER_NUM
它控制预分配和预注册的内存量。它的默认值是16
,所以你可能想减少它。但请注意可能的性能影响。您还可以尝试通过设置使用动态预分配的缓冲区大小I_MPI_DAPL_BUFFER_ENLARGEMENT
to 1
。启用此选项后,英特尔 MPI 最初会注册小型缓冲区,并在需要时稍后扩大它们。另请注意,IMPI 会延迟打开连接,这就是为什么仅在调用后才看到已用内存大幅增加的原因MPI_Send
.
如果不使用 DAPL 传输,例如使用ofa
相反,您无能为力。您可以通过设置启用 XRC 队列I_MPI_OFA_USE_XRC
to 1
。这应该会以某种方式减少使用的内存。还可以通过设置启用动态队列对创建I_MPI_OFA_DYNAMIC_QPS
to 1
如果程序的通信图未完全连接(完全连接的程序是每个级别与所有其他级别通信的程序),可能会减少内存使用量。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)