A M*_*rii 8 python numpy ipython jupyter jupyter-notebook
我目前正在 kaggle 中开发 jupyter notebook。在我的 numpy 数组上执行所需的转换后,我对其进行了腌制,以便将其存储在磁盘上。我这样做的原因是我可以释放大数组消耗的内存。
酸洗阵列后消耗的内存约为 8.7 GB。
我决定运行此代码通过@扬GLX代码段中提供在这里,找出变量占用我的记忆:
import sys
def sizeof_fmt(num, suffix='B'):
''' by Fred Cirera, /sf/answers/76645341/, 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)))
Run Code Online (Sandbox Code Playgroud)
执行此步骤后,我注意到数组的大小为 3.3 gb,所有其他变量的大小加在一起约为 0.1 gb。
我决定通过执行以下操作来删除数组并查看是否可以解决问题:
del my_array
gc.collect()
Run Code Online (Sandbox Code Playgroud)
这样做之后,内存消耗从 8.7 GB 减少到 5.4 GB。这在理论上是有道理的,但仍然没有解释剩余的内存是由什么消耗的。
我决定继续并重置我的所有变量,看看这是否会释放内存:
%reset
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,它释放了上面函数中打印出的变量的内存,而我仍然有 5.3 GB 的内存在使用。
需要注意的一件事是,我在酸洗文件本身时注意到内存峰值,因此该过程的摘要如下所示:
请注意,以上内容是基于对 kaggle 内存的监控,可能不准确。我也检查了这个问题,但对我的情况没有帮助。
这会被认为是内存泄漏吗?如果是这样,在这种情况下我该怎么办?
编辑 1:
经过进一步挖掘,我注意到还有其他人面临这个问题。这个问题源于酸洗过程,酸洗在内存中创建了一个副本,但由于某种原因,并没有释放它。酸洗过程完成后有没有办法释放内存。
编辑2:
从磁盘中删除腌制文件时,使用:
!rm my_array
Run Code Online (Sandbox Code Playgroud)
它最终释放了磁盘空间并释放了内存空间。我不知道上面的花絮是否有用,但我决定将它包括在内,因为每一点信息都可能有所帮助。
您应该注意一个基本缺点:CPython 解释器实际上几乎无法释放内存并将其返回给操作系统。对于大多数工作负载,您可以假设在解释器进程的生命周期内不会释放内存。然而,解释器可以在内部重用内存。所以从操作系统的角度来看CPython进程的内存消耗确实没有任何帮助。一个相当常见的解决方法是在子进程/工作进程中运行内存密集型作业(例如通过多处理),并“仅”将结果返回到主进程。一旦工人死亡,内存实际上就被释放了。
其次,使用sys.getsizeof
on ndarray
s 可能会产生严重的误导。请ndarray.nbytes
改用该属性,并注意在处理视图时这也可能会产生误导。
此外,我不完全确定为什么你“pickle”numpy 数组。有更好的工具可以完成这项工作。仅举两个:h5py(经典,基于HDF5)和zarr。这两个库都允许您直接在磁盘上处理ndarray
类似的对象(和压缩)——基本上消除了酸洗步骤。此外,zarr 还允许您在内存中创建压缩 ndarray
兼容的数据结构。来自 numpy、scipy 和朋友的Mustufunc
会很乐意接受它们作为输入参数。