当前位置: 首页 > 面试题库 >

对于小型/大型numpy数组,释放方式是否有所不同?

徐学潞
2023-03-14
问题内容

我正在尝试使用大型Python应用程序调试内存问题。大部分内存在numpyPython类管理的数组中,因此Heapy等无用,因为它们不占numpy数组中的内存。因此,我尝试使用MacOSX(10.7.5)活动监视器(或者top如果愿意)来手动跟踪内存使用情况。我注意到以下奇怪的行为。在普通python解释器外壳(2.7.3)上:

import numpy as np # 1.7.1
# Activity Monitor: 12.8 MB
a = np.zeros((1000, 1000, 17)) # a "large" array
# 142.5 MB
del a
# 12.8 MB (so far so good, the array got freed)
a = np.zeros((1000, 1000, 16)) # a "small" array
# 134.9 MB
del a
# 134.9 MB (the system didn't get back the memory)
import gc
gc.collect()
# 134.9 MB

不管我做什么,Python会话的内存占用都不会再低于134.9 MB。所以我的问题是:

为什么大于1000x1000x17x8字节(根据经验在我的系统上找到)的数组资源会正确地分配回系统,而较小数组的内存似乎永远都被Python解释器卡住了?

这似乎确实增加了,因为在我的实际应用程序中,我最终获得了超过2
GB的内存,而我再也无法从Python解释器中找回内存。Python会根据使用历史记录来保留越来越多的内存吗?如果是,那么对于我的案例,Activity
Monitor就像Heapy一样没用。那里有没有没有用的东西吗?


问题答案:

从读NumPy的政策释放的内存好像numpy没有
有内存分配/释放的任何特殊处理。它仅free()在参考计数为零时调用。实际上,使用任何内置的python对象复制问题都是非常容易的。问题出在操作系统级别。

纳撒尼尔·史密斯(Nathaniel Smith)在链接html" target="_blank">线程的其中一封答复中写了一个解释:

通常,进程可以从OS请求内存,但 不能将其退还给
内存。在C级别上,如果您调用free(),那么实际发生的情况是您进程中的内存管理库自己记录了该内存未使用的情况,并且可能会在将来malloc()从操作系统中将其返回,但是从操作系统的角度来看仍然是“已分配”。(并且python在malloc()/之上使用了另一个类似的系统
free(),但这并没有真正改变任何东西。)因此,您看到的OS内存使用率通常是“高水位线”,即您的进程曾经需要的最大内存量。

唯一的例外是,对于较大的单个分配(例如,如果您创建一个多兆字节的数组),则使用不同的机制。如此大的内存分配 可以
释放回OS。因此,具体来说,可能是numpy程序的某些部分导致了所看到的问题。

因此,似乎没有通用的解决方案。分配许多小对象将导致工具所描述的“高内存使用率”,即使您将在需要时将其重用,同时分配大对象也不会显示大内存。释放后使用,因为操作系统回收了内存。

您可以验证此分配的内置python对象:

In [1]: a = [[0] * 100 for _ in range(1000000)]

In [2]: del a

在执行此代码后,我可以看到在执行以下操作时 回收内存:

In [1]: a = [[0] * 10000 for _ in range(10000)]

In [2]: del a

内存 回收。

为了避免出现内存问题,你应该分配的大阵列,并与他们的工作(也许使用视图来“模拟”小数组?),还是尽量避免有许多小数组 在同一时间
。如果您有一些创建小对象的循环,则可以显式地取消分配每次迭代不需要的对象,而不是仅在最后执行此操作。

我相信Python内存管理可以很好地了解如何在python中管理内存。请注意,除了“操作系统问题”之外,python还添加了另一层来管理内存区域,这可能会导致小对象占用大量内存。



 类似资料:
  • 问题内容: 我来自php背景,在php中,有一个函数可以告诉您数组中使用了多少个元素。 数组有类似的方法吗?谢谢。 问题答案: 是的(类属性,而不是方法):

  • 在java中,不能使用。compareTo()将基元类型(如int)与其他类型进行比较。 如果两个整数小于零,有没有办法比较?我试图将整数与数组中的点进行比较。 谢啦! 解决方法:抱歉,大家都有一秒钟的大脑抽筋。我忘记了a.compareTo(b)根据第一个值是否小于(返回-1)、等于(返回0)或大于(返回1)返回-1、0或1。我的代码是int.compareTo(数组)

  • 我使用Oracle数据库和驱动程序,我使用从ResultSet获取Clob,然后在方法中将其转换为String:

  • 问题内容: 在NumPy中,我可以通过以下方式获取特定数据类型的大小(以字节为单位): 要么: 例如: 我有两个问题。首先,有没有一种方法可以在 不创建 数据类型 实例的情况 下获取此信息?其次,和之间有什么区别? 问题答案: 您需要一个的实例来获取itemsize,但不需要一个的实例。(很快就会知道,它是数组的属性,而不是dtype。) 例如 至于之间的区别和,只是。 例如

  • 问题内容: 我对等待和通知/ notifyAll感到有些困惑。 我知道每个Java对象都有一个锁。我知道等待将释放其他线程的锁。notify / notifyall怎么样?notify / notifyAll是否释放它为其他线程持有的锁? 问题答案: 否- / 不要像那样释放锁。唤醒的线程直到调用的代码释放其锁后才能运行。 这就是Javadoc所说的: 该线程释放此监视器的所有权,并等待直到另一个

  • 为了生成某些情况下的概率密度函数,可能需要考虑100万次观测。当我使用numpy数组时,遇到了大小限制32。 是不是太少了? 在这种情况下,我们如何存储32个以上的元素,而不将元素分布到不同的列中,或者在数组中分布数组?