逐步构建numpy数组并测量内存使用情况

11 投票
4 回答
6639 浏览
提问于 2025-04-15 14:53

我有一系列很大的文本文件(最大可达1GB),这些文件是实验的输出,需要在Python中进行分析。最好的方式是把它们加载到一个二维的numpy数组中,这就引出了第一个问题:

  • 由于在加载时不知道行数,如何最有效地逐行构建一个非常大的numpy数组呢?

简单地把行添加到数组中在内存上会很低效,因为两个大数组会暂时同时存在。使用numpy.append似乎也会遇到同样的问题。虽然stack函数看起来不错,但我更希望能在原地扩展数组。

这就引出了第二个问题:

  • 观察一个大量使用numpy数组的Python程序的内存使用情况,最好的方法是什么?

为了研究上述问题,我使用了常见的内存分析工具——heapy和pympler,但我只能得到外部数组对象的大小(80字节),而无法看到它们包含的数据。除了粗略测量Python进程使用了多少内存外,还有什么办法可以获取数组在增长时的“完整”大小呢?

本地信息:OSX 10.6,Python 2.6,但欢迎提供一般性的解决方案。

4 个回答

1

一个可行的办法是先简单地浏览一下文件,先统计一下有多少行,而不需要把所有行都加载进来。

另一个办法是每次把表的大小翻倍,这样有两个好处:

  1. 你只需要重新分配内存大约 log(n) 次,其中 n 是行数。
  2. 你只需要比你最大表的大小多 50% 的内存。

如果你选择动态调整的方式,可以先测量第一行的字节长度,然后通过计算(文件中的字节数 / 第一行的字节数)来估算行数。然后就可以从这个大小的表开始。

2

你试过使用内存映射文件吗?你可以分块读取你的输入文件,然后把读取到的数据转换成行,插入到一个内存映射的numpy数组里。如果你的主内存不够用,这样做的缺点是会增加磁盘的读写次数,因为可能需要使用交换空间。

详细信息请查看:http://docs.scipy.org/doc/numpy/reference/generated/numpy.memmap.html

另一个选择是PyTables。你需要构建一些类似SQL的特殊表格,但其实挺简单的。实际上,它可以自动保存数据(就像把数据打包起来一样),并且可以对数据进行层次化组织。它还可以限制使用的主内存量。

详细信息请查看:www.pytables.org/moin/HowToUse

祝你好运!

7

要想在原地扩展数组,唯一的方法就是先创建一个最大可能大小的空数组(用numpy.empty),然后在最后使用这个数组的视图。你不能一开始就创建一个小的数组,因为没有办法保证你可以在不影响其他数据的情况下扩展内存。(而且这一切都比Python在解释器内部允许你做的要低级得多。)

你最好的选择可能是 numpy.fromiter。从源代码来看,随着项目数量的增加,数组每次会扩展大约50%。如果你能轻松获取行数(比如通过计算行数),你甚至可以给它传递一个计数。

撰写回答