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


我有一系列大型文本文件(最多1个gig),这些文件是从需要在Python中分析的实验中输出的。它们最好加载到2D numpy数组中,这是第一个问题:

  • 由于在加载开始时行数未知,怎么可能 一个非常大的numpy数组是最有效地逐行构建的?

简单地将行添加到数组中在内存方面效率很低,因为两个大型数组会暂时共存。如果使用,似乎会出现同样的问题 numpy.append。该 stack 函数是有前途的,但理想情况下我希望将数组增加到位。

这导致了第二个问题:

  • 观察Python程序内存使用情况的最佳方法是什么? 使用numpy数组?

为了研究上面的问题,我使用了通常的内存分析工具 - heapy和pympler - 但我只得到外部数组对象的大小(80字节)而不是它们包含的数据。除了粗略测量Python进程使用多少内存之外,如何在数组增长时获得“完整”大小?

本地详细信息:OSX 10.6,Python 2.6,但欢迎使用一般解决方案。


1276
2017-10-07 11:08


起源



答案:


除了创建最大可能大小的空数组(numpy.empty),然后在最后使用视图时,无法确保您可以将数组增长到位。你不能从小做起,因为不能保证你可以扩展地图的任何内存,而不会破坏其他一些数据。 (所有这些都比python低得多,允许你从解释器内部获得。)

你最好的选择可能就是 numpy.fromiter。查看源,随着项目数量的增加,阵列每次扩展50%以上。如果你可以很容易地获得行数(比如计算行数),你甚至可以传递一个计数。


7
2017-10-07 21:14





你尝试过使用memmap文件吗?您可以迭代输入文件(如果可能,以块为单位)并转换传入数据并将它们作为行插入到内存映射的numpy数组中。缺点是在主内存不足的情况下会产生更多的磁盘I / O,并且需要从交换中进行分页。

看到: http://docs.scipy.org/doc/numpy/reference/generated/numpy.memmap.html

另一种选择是PyTables。你需要构建一些特殊的类似sql的表,但它相当简单。实际上,它为您的数据提供透明磁盘持久性(自动序列化)和分层组织。它还限制了使用的主内存量。

请参阅:www.pytables.org/moin/HowToUse

祝你好运!


2
2018-01-12 07:05





可能的选择是首先对文件进行单次传递以计算行数,而不加载它们。

另一种选择是每次将表大小加倍,这有两个好处:

  1. 您将只重新分配内存log(n)次,其中n是行数。
  2. 你只需要比你最大的桌子大50%的ram

如果采用动态路由,则可以测量第一行的长度(以字节为单位),然后通过计算(第一行中的num / num字节数)来猜测行数。从这个大小的表开始。


1
2017-10-07 21:32



谢谢大家。鉴于文件的大小,我不愿意只计算行数的初始传递,但它似乎是解决内存问题的最简单,最有效的方法。
我最近有一个同事问了一个类似的问题,我想出了另一种可能让你从最初的传球中解脱出来的可能性。如果您知道文件中“元素”的大致大小,则可以将其分成文件大小。添加一些填充以确保安全,然后您可以写入整个内存。要隐藏额外的未初始化,您可以仅使用包含数据的元素的视图。你需要确保你不要过去。它并不完美,但是如果您的文件读取速度很慢,并且您的数据一直是布局的,那么它可能会起作用。 - AFoglia


答案:


除了创建最大可能大小的空数组(numpy.empty),然后在最后使用视图时,无法确保您可以将数组增长到位。你不能从小做起,因为不能保证你可以扩展地图的任何内存,而不会破坏其他一些数据。 (所有这些都比python低得多,允许你从解释器内部获得。)

你最好的选择可能就是 numpy.fromiter。查看源,随着项目数量的增加,阵列每次扩展50%以上。如果你可以很容易地获得行数(比如计算行数),你甚至可以传递一个计数。


7
2017-10-07 21:14





你尝试过使用memmap文件吗?您可以迭代输入文件(如果可能,以块为单位)并转换传入数据并将它们作为行插入到内存映射的numpy数组中。缺点是在主内存不足的情况下会产生更多的磁盘I / O,并且需要从交换中进行分页。

看到: http://docs.scipy.org/doc/numpy/reference/generated/numpy.memmap.html

另一种选择是PyTables。你需要构建一些特殊的类似sql的表,但它相当简单。实际上,它为您的数据提供透明磁盘持久性(自动序列化)和分层组织。它还限制了使用的主内存量。

请参阅:www.pytables.org/moin/HowToUse

祝你好运!


2
2018-01-12 07:05





可能的选择是首先对文件进行单次传递以计算行数,而不加载它们。

另一种选择是每次将表大小加倍,这有两个好处:

  1. 您将只重新分配内存log(n)次,其中n是行数。
  2. 你只需要比你最大的桌子大50%的ram

如果采用动态路由,则可以测量第一行的长度(以字节为单位),然后通过计算(第一行中的num / num字节数)来猜测行数。从这个大小的表开始。


1
2017-10-07 21:32



谢谢大家。鉴于文件的大小,我不愿意只计算行数的初始传递,但它似乎是解决内存问题的最简单,最有效的方法。
我最近有一个同事问了一个类似的问题,我想出了另一种可能让你从最初的传球中解脱出来的可能性。如果您知道文件中“元素”的大致大小,则可以将其分成文件大小。添加一些填充以确保安全,然后您可以写入整个内存。要隐藏额外的未初始化,您可以仅使用包含数据的元素的视图。你需要确保你不要过去。它并不完美,但是如果您的文件读取速度很慢,并且您的数据一直是布局的,那么它可能会起作用。 - AFoglia


问题基本上是文本文件。当您的输入数据存储在更高级的时候,可以避免这样的问题。举个例子来看看 h5py项目。首先将数据转换为HDF5文件然后在HDF5文件上运行分析脚本是值得的。


0
2018-02-12 11:13