我目前正在 kaggle 中开发 jupyter 笔记本。在我的 numpy 数组上执行所需的转换后,我将其腌制以便可以将其存储在磁盘上。我这样做的原因是为了释放大数组消耗的内存。
pickle 阵列后消耗的内存约为 8.7 GB。
我决定运行 @jan-glx 提供的代码片段here https://stackoverflow.com/a/51046503/12403182,找出哪些变量消耗了我的内存:
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 的内存在使用中。
需要注意的一件事是,我在腌制文件本身时注意到内存峰值,因此该过程的摘要如下所示:
- 对数组执行操作 -> 内存消耗从大约 1.9 GB 增加到 5.6 GB
- pickled 文件 -> 内存消耗从 5.6 GB 增加到约 8.7 GB
- 当文件被 pickle 到 15.2 GB 时,内存突然激增,然后又回落到 8.7 GB。
- 删除的数组 -> 内存消耗从 8.7 GB 减少到 5.4 GB
- 执行重置 -> 内存消耗从 5.4 GB 减少到 5.3 GB
请注意,上述内容大致基于监控 Kaggle 上的内存,可能不准确。
我也检查过这个question https://stackoverflow.com/questions/56126062/how-to-destroy-python-objects-and-free-up-memory但这对我的案子没有帮助。
这会被视为内存泄漏吗?如果是这样,在这种情况下我该怎么办?
EDIT 1:
经过进一步挖掘,我注意到有others https://stackoverflow.com/questions/13871152/why-pickle-eat-memory面临这个问题。这个问题源于酸洗过程,酸洗会在内存中创建一个副本,但由于某种原因,不会释放它。有没有办法在酸洗过程完成后释放内存。
EDIT 2:
从磁盘删除 pickled 文件时,使用:
!rm my_array
它最终释放了磁盘空间并释放了内存空间。我不知道上面的花絮是否有用,但我决定无论如何都将其包括在内,因为每一点信息都可能有所帮助。