【问题标题】:Jupyter Notebook Memory ManagementJupyter 笔记本内存管理
【发布时间】:2020-06-11 09:38:27
【问题描述】:

我目前正在 kaggle 中开发一个 jupyter notebook。在对我的 numpy 数组执行所需的转换后,我将其腌制,以便可以将其存储在磁盘上。我这样做的原因是我可以释放大数组消耗的内存。

酸洗阵列后消耗的内存约为 8.7 GB。

我决定运行@jan-glx here 提供的这段代码sn-p,找出哪些变量正在消耗我的内存:

import sys

def sizeof_fmt(num, suffix='B'):
    ''' by Fred Cirera,  https://*.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 的内存在使用。

需要注意的一点是,我在 pickling 文件本身时注意到内存峰值,因此该过程的摘要如下所示:

  1. 对数组执行操作 -> 内存消耗从大约 1.9 gb 增加到 5.6 gb
  2. 腌制文件 -> 内存消耗从 5.6 gb 增加到大约 8.7 gb
  3. 在文件被腌制到 15.2 gb 时内存突然激增,然后又回落到 8.7 gb。
  4. 已删除数组 -> 内存消耗从 8.7 gb 减少到 5.4 gb
  5. 执行重置 -> 内存消耗从 5.4 gb 减少到 5.3 gb

请注意,以上内容是基于监控 kaggle 上的内存,可能不准确。 我也检查了这个question,但这对我的情况没有帮助。

这会被认为是内存泄漏吗?如果是这样,在这种情况下我该怎么办?

编辑1:

经过进一步挖掘,我注意到有others 面临这个问题。这个问题源于酸洗过程,酸洗会在内存中创建一个副本,但由于某种原因不会释放它。酸洗过程完成后有没有办法释放内存。

编辑2:

从磁盘中删除腌制文件时,使用:

!rm my_array 

它最终释放了磁盘空间并释放了内存空间。我不知道上面的花絮是否有用,但我还是决定把它包括在内,因为每一点信息都可能有所帮助。

【问题讨论】:

    标签: python numpy jupyter-notebook ipython jupyter


    【解决方案1】:

    您应该注意一个基本缺点:CPython 解释器实际上是can actually barely free memory and return it to the OS。对于大多数工作负载,您可以假设在解释器进程的生命周期内没有释放内存。但是,解释器可以在内部重用内存。所以从操作系统的角度来看CPython进程的内存消耗真的一点帮助都没有。一个相当常见的解决方法是在子进程/工作进程中运行内存密集型作业(例如通过multiprocessing)并“仅”将结果返回给主进程。一旦worker死亡,内存实际上就被释放了。

    其次,在ndarrays 上使用sys.getsizeof 可能会产生令人印象深刻的误导。请改用ndarray.nbytes 属性,并注意这在处理views 时也可能会产生误导。

    此外,我不完全确定您为什么要“腌制” numpy 数组。这项工作有更好的工具。仅举两个例子:h5py(经典,基于HDF5)和zarr。这两个库都允许您直接在磁盘上使用类似ndarray 的对象(和压缩)——基本上消除了酸洗步骤。此外,zarr 还允许您create compressed ndarray-compatible data structures in memory。 must ufuncs from numpy, scipy & friends 会很乐意接受它们作为输入参数。

    【讨论】: