如何处理Python中的大内存占用问题?

3
我有一个科学应用程序,从磁盘读取可能非常大的数据文件,并将其转换为各种Python数据结构,如地图和列表等。在进行数值分析时需要调用NumPy。问题是内存使用量会快速增长。当调用交换空间时,系统会明显变慢。我看到的一般策略有:
  1. 惰性初始化:这似乎无助于许多操作仍需要内存中的数据。
  2. Shelving:此Python标准库似乎支持将数据对象写入数据文件(由某个数据库支持)。我的理解是它会将数据转储到文件中,但如果需要,仍需将所有数据加载到内存中,因此实际上并没有什么帮助。如果我有误,请纠正我。
  3. 第三种选择是利用数据库,并将尽可能多的数据处理卸载到数据库中。
例如:科学实验运行了几天并生成了大量(tera字节的数据)以下序列:

在时间t观察到坐标(x,y)的事件E。

我们需要计算每个(x,y)的t直方图并输出一个三维数组。
还有其他建议吗?我想我的理想情况是,可以根据软内存限制将内存中的数据结构分阶段转移到磁盘,并且这个过程应该尽可能透明。这些缓存框架中的任何一个可以帮助吗?
编辑:非常感谢所有提供的建议和指导。其中,我认为用户488551的评论最相关。尽管我喜欢Map/Reduce,但对于许多科学应用程序来说,代码并行化的设置和工作是更大的难题,比起我最初的问题来说更难解决。因此,在实际情况中,Bill的答案更接近我们所能做到的,因此我选择了他的答案。感谢大家。

你用性能分析器检查过吗?可能会有一些你意想不到的问题,比如在某个循环中进行了不必要的内存分配。 - rapadura
你的工作量不应该无限增长。有没有办法在任何给定的计算量上设置理论上的数据限制呢? - millimoose
"许多操作无论如何都需要内存数据"? 在这个问题上,你必须更加精确。为了减少内存占用,你需要将问题分解成较小的部分,虽然运行速度较慢,但使用的内存较少。 - S.Lott
2个回答

3
你考虑过分而治之吗?也许你的问题适合这种方法。你可以使用 Map/Reduce 框架来实现。
你的问题是否有多个阶段,第一阶段需要一些数据作为输入,并生成一个可以传递给第二阶段的输出?如果是这样,你可以让一个进程执行第一阶段并生成第二阶段的数据。也许这样可以减少同时需要在内存中存储的数据量?
你能否将问题分成许多小问题并重新组合解决方案?在这种情况下,你可以生成多个进程,每个进程处理一个小的子问题,并有一个或多个进程在最后组合这些结果?
如果 Map-Reduce 适用于你的问题,请看看 Hadoop 框架。

1

如果你需要将整个数据集存储在RAM中,除了增加RAM之外,没有什么可做的了。听起来你不确定是否真的需要这样做,但保持所有数据驻留需要最少的思考。

如果你的数据在长时间内以流的形式到来,并且你所做的只是创建一个直方图,那么你不需要将它全部存储下来。随着数据的到来,逐步创建直方图,如果你想要稍后使用原始数据,将其写入文件,让Python在你增加直方图计数器后立即回收数据。你只需要保留直方图本身,这应该相对较小。


这里有一个警告,即2D(或3D)直方图不一定很小 - 特别是如果数据相对稀疏。我遇到过它们比原始数据点大得多的情况。 - user488551
上一个评论超时了...如果您的直方图太大,仍然有一种清晰的方法来分离数据/处理(在每个时间bin上使用2D直方图),但我建议使用pytables(www.pytables.org)来存储结果直方图。这为您提供了缓存、可附加的磁盘存储,看起来像ndarray,但只在读取时加载数据。我经常用它来处理图像流。 - user488551
稀疏直方图的好处在于,您肯定希望将表示与数据的预期特征相匹配。 - Bill Gribble

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