我目前正在kaggle中从事Jupyter笔记本的研究。在numpy数组上执行所需的转换后,我对其进行了腌制,以便可以将其存储在磁盘上。我这样做的原因是为了释放大型阵列消耗的内存。
腌制阵列后消耗的内存约为8.7 gb。
我决定运行@ jan-glx在此处提供的代码段,以找出哪些变量正在占用我的内存:
import sys
def sizeof_fmt(num, suffix='B'):
''' by Fred Cirera, https://stackoverflow.com/a/1094933/1870254, modified'''
for unit in ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']:
if abs(num) < 1024.0:
return "%3.1f %s%s" % (num, unit, suffix)
num /= 1024.0
return "%.1f %s%s" % (num, 'Yi', suffix)
for name, size in sorted(((name, sys.getsizeof(value)) for name, value in locals().items()),
key= lambda x: -x[1])[:10]:
print("{:>30}: {:>8}".format(name, sizeof_fmt(size)))
执行完此步骤后,我注意到我的数组的大小为3.3 gb,所有其他变量的总和约为0.1 gb。
我决定删除数组,并通过执行以下操作来查看是否可以解决问题:
del my_array
gc.collect()
执行此操作后,内存消耗从8.7 gb减少到5.4 gb。从理论上讲这是有意义的,但仍然没有解释剩余的内存被消耗了什么。
我决定还是继续并重置所有变量,以查看是否可以通过以下方式释放内存:
%reset
不出所料,它释放了上面函数中打印出的变量的内存,而我仍然剩下5.3 gb的可用内存。
需要注意的一件事是,我在腌制文件本身时注意到内存高峰,因此该过程的摘要如下所示:
请注意,以上内容是基于监视kaggle上的内存的松散基础,可能不准确。我也检查了这个问题,但对我的情况没有帮助。
这会被视为内存泄漏吗?如果是这样,在这种情况下我该怎么办?
编辑1:
经过进一步的挖掘,我注意到还有其他人面临这个问题。此问题源于酸洗过程,酸洗会在内存中创建一个副本,但由于某种原因不会释放它。酸洗过程完成后,有没有办法释放内存。
编辑2:
从磁盘删除腌制的文件时,使用:
!rm my_array
最终释放了磁盘空间,还释放了内存空间。我不知道上面的提示是否有用,但我还是决定将其包括在内,因为每一点信息都可能有所帮助。
您应该意识到一个基本的缺点:CPython解释器实际上几乎不能释放内存并将其返回给OS。对于大多数工作负载,您可以假定在解释程序的生命周期内没有释放内存。但是,解释器可以在内部重新使用内存。因此,从操作系统的角度来看CPython进程的内存消耗确实没有任何帮助。一个相当普遍的解决方法是在子进程/工作进程(例如,通过多处理)中运行占用大量内存的作业,然后“仅”将结果返回给主进程。一旦工人死亡,实际上就释放了内存。
第二,sys.getsizeof
在上使用ndarray
可能会令人产生误导。请改用该ndarray.nbytes
属性,并且要注意,在处理视图时,这也可能会产生误导。
此外,我不完全确定为什么要“刺入” numpy数组。有更好的工具来完成这项工作。仅举两个例子:h5py(基于HDF5的经典版本)和zarr。这两个库都允许您ndarray
直接在磁盘上(和压缩)使用类似对象的对象-实质上消除了酸洗步骤。此外,zarr还允许您在memory中创建压缩 ndarray
兼容的数据结构。ufunc
来自numpy的Must ,scipy和朋友将很乐意接受它们作为输入参数。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句