我用C ++编写了一个需要大量内存的计算机模拟。它在迭代中运行,并且在每次迭代中分配大量内存,这些内存应该在迭代结束时释放。它还使用c ++ 11的<thread>
实现来并行运行东西。
当我在桌面计算机上测试程序时,它表现良好:它永远不会超过我允许的内存,在时间和迭代期间,没有任何内容堆积起来。但是,当我将程序提交给我们的计算集群时,所使用的内存(我只能通过排队软件访问)随着时间的推移而增长,并且远远超过了我的计算机上使用的内存。
让我首先向您展示软件的结构:
for thread in n_threads:
vector<Object> container;
for iteration in simulation:
container.clear()
container.resize(a_large_number)
... do stuff ...
让我们说,在我的机器上,容器会耗尽2GB
内存。我可以在htop
和valgrind --tool=massif
中看到这些2GB
永远不会被超越。没有什么可以堆积的。但是,在集群上,我可以看到内存增长和增长,直到它变得远远超过2GB
(并且作业被终止/计算节点冻结......)。请注意,我限制了两台机器上的线程数量,并且可以确保它们是相同的。
我所知道的是,群集上的libc
已经很老了。为了编译我的程序,我需要编译新版本的g++
并更新集群前端节点上的libc
。该软件在计算节点上运行良好(除了这个内存问题),但libc在那里更老了。这可能是一个问题,特别是与线程一起,用于内存分配?我怎么调查呢?
答案 0 :(得分:1)
是的,根据GNU libc的年龄,您可能会遗漏一些重要的内存分配优化。以下是一些可以尝试的事情(不用说,冒着性能损失的风险):
您可以尝试通过mallopt()
调整malloc / free行为;使用M_MMAP_MAX
和M_MMAP_THRESHOLD
选项可以鼓励更多分配通过mmap()
,这样可以保证在free()
之后将内存返回给系统。
尝试将容器的分配器设为__gnu_cxx::malloc_allocator
,以确保mallopt()
调整影响容器。
请在调整大小后尝试调用container.shrink_to_fit()
,以确保该向量不会扣留超出严格要求的内存。