我目前正在kaggle中从事Jupyter笔记本的研究。在numpy数组上执行所需的转换后,我对其进行了腌制,以便可以将其存储在磁盘上。我这样做的原因是为了释放大型阵列消耗的内存。
腌制阵列后消耗的内存约为8.7 gb。
我决定运行@ jan-glx here提供的代码段,以找出哪些变量正在占用我的内存:
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上的内存的宽松方式,可能不准确。 我还检查了此question,但对我的情况没有帮助。
这将被视为内存泄漏吗?如果是这样,在这种情况下我该怎么办?
编辑1:
进一步研究之后,我发现有others面临此问题。此问题源于酸洗过程,酸洗会在内存中创建一个副本,但由于某种原因不会释放它。酸洗过程完成后,是否可以释放内存。
编辑2:
从磁盘删除腌制的文件时,使用:
!rm my_array
它最终释放了磁盘空间,还释放了内存空间。我不知道上面的提示是否有用,但我还是决定将其包括在内,因为每一点信息都可能有所帮助。
答案 0 :(得分:1)
您应该意识到一个基本的缺点:CPython解释器实际上是can actually barely free memory and return it to the OS。对于大多数工作负载,您可以假定在解释程序的生命周期中没有释放内存。但是,解释器可以在内部重新使用内存。因此,从操作系统的角度来看CPython进程的内存消耗确实没有任何帮助。一个相当普遍的解决方法是在子进程/工作进程(例如,通过multiprocessing)中运行占用大量内存的作业,然后“仅”将结果返回给主进程。工人死后,实际上释放了内存。
第二,在 <pre>
<code>
HTML code goes
here.
</code>
</pre>
上使用 @objc func sectionHeaderTapped(_ recognizer: UITapGestureRecognizer) {
headerView.removeFromSuperview()
...
}
可能会令人产生误解。请改用sys.getsizeof
属性,请注意,在处理views时,这也可能会产生误导。
此外,我不完全确定为什么要“刺破” numpy数组。有更好的工具来完成这项工作。仅举两个例子:h5py(基于HDF5的经典作品)和zarr。这两个库都允许您直接在磁盘上(和压缩)使用类似ndarray
的对象-基本上消除了酸洗步骤。此外,zarr还允许您create compressed ndarray
-compatible data structures in memory。来自numpy,scipy和朋友的ndarray.nbytes
人必须愉快地接受它们作为输入参数。