【问题标题】:Memory Leak in Python/Jupyter NotebookPython/Jupyter Notebook 中的内存泄漏
【发布时间】:2021-07-25 03:10:19
【问题描述】:

通过在 单个 Jupyter Notebook 单元格中运行仅以下代码,我在函数的内存中加载了 1GB 的文件,然后我返回函数定义后的结果:

import pickle

def fun():
    with open('./data/input/train_test_clevr_pkls/train_clevr_1000.pkl', 'rb') as handle:
        return pickle.load(handle)

fun()

Jupyter Notebook 然后将打印函数的输出。查看运行单元后消耗的内存,它如预期的那样位于 1GB。但是,如果我多次运行同一个单元,内存占用量每次增加 1GB,直到我的整个 RAM 被消耗,然后我的 Windows 操作系统使用页面文件交换来处理标记为已消耗的更多内存,这会破坏我的应用程序的性能。我已经尝试使用gc.collect() 释放内存,但无济于事。

我看到有人问过类似的问题,但我没有找到问题的答案。内存不在内部被重用,它只会增长!

【问题讨论】:

  • 如果您在与fun() 调用相同的单元格中执行gc.collect()
  • 如果我在同一个单元格中使用gc.collect(),在fun() 调用之后内存不会泄漏并且垃圾收集器返回0,这意味着它没有收集任何东西。或者,如果我将调用包装成类似print(fun()) 或在fun() 之后添加任何指令,则不再存在内存泄漏。但是我仍然不明白为什么它首先泄漏,除非我重新启动内核,否则我无法恢复初始内存丢失。

标签: python python-3.x memory-leaks jupyter-notebook


【解决方案1】:

您看到这个的原因是因为 Jupyter 将所有引用存储到一个名为 Out 的名称。

MRE(所有这些都在一个单元格中)

from itertools import product

def foo():
    return [*product(range(5), repeat=5)]

[foo() for _ in range(5)]

当你在单元格中运行它时,Jupyter 会将它保存到字典 Out。

Out的部分内容

{1: [[(0, 0, 0, 0, 0),
   (0, 0, 0, 0, 1),
   (0, 0, 0, 0, 2),
   (0, 0, 0, 0, 3),
   (0, 0, 0, 0, 4),
   (0, 0, 0, 1, 0),
   (0, 0, 0, 1, 1),
   (0, 0, 0, 1, 2),
   (0, 0, 0, 1, 3),
   (0, 0, 0, 1, 4),
   (0, 0, 0, 2, 0),
   (0, 0, 0, 2, 1),...}

当您再次运行代码块时,它会将该值存储到 Out 中的新键 3。每次运行单元格时,这都会不断向Out dict 添加新的键值对。

现在是print(...)时没有发生的原因

from itertools import product

def foo():
    return [*product(range(5), repeat=5)]

print([foo() for _ in range(5)])

在这种情况下,Jupyter 不会将结果保存到 Out 字典中。无论您运行多少次单元格,Out dict 将始终为{}。

【讨论】:

  • 将删除/清除Out 单元格释放内存
  • 我确实尝试了Out.clear() 和Out = {} 和del Out,但没有奏效,我在任务管理器中的内存使用保持不变@rioV8
  • 我的意思是清除/删除 GUI 中的 [2] 单元格
  • 您的意思是右键单击“删除单元格”?如果是这样,那么我只是尝试过,它不会释放 RAM
  • [*product(range(5), repeat=5)] 是一种复杂的写法list(product(range(5), repeat=5)),为什么你有 2-tuples 而不是 5-tuples (repeat=5)
猜你喜欢
  • 2012-12-02
  • 2011-12-13
  • 2014-02-26
  • 2010-11-27
  • 1970-01-01
  • 2015-02-15
  • 1970-01-01
  • 1970-01-01
  • 2019-07-12
相关资源
最近更新 更多