【问题标题】:Python memory increases despite garbage collection尽管有垃圾收集,Python 内存仍会增加
【发布时间】:2018-03-19 18:14:01
【问题描述】:

我正在尝试以类似 MapReduce 的方式使用多个线程来计算大量文档中大量单词的出现次数。每个线程都从一个字典开始,将语料库中的每个单词映射为零,并在遍历文档时递增计数。完成所有线程后,我想累积计数。我将第一个 json 文件加载到内存中,然后循环遍历其余文件,对计数求和:

def merge_counts(self):
    path = os.path.join(self.get_current_job_directory(), 'batch_0.json') 
    with open (path, 'r') as json_file:
        kmers = json.load(json_file)
    batch = None
    for i in range(1, self.num_threads):
        path = os.path.join(self.get_current_job_directory(), 'batch_' + str(i) + '.json') 
        with open (path, 'r') as json_file:
            batch = json.load(json_file)
            for kmer in batch:
                kmers[kmer] += batch[kmer]
        batch = None
    return kmers

这里的kmers 是包含所有最终计数的最终字典。无论加载多少批次,kmers 中的键数量都保持不变,因为它们都具有相同的键,只是计数不同。每个 json 文件大约 3 gig 大,因此最终结果也大致相同。我希望这段代码使用与在内存中保存两个这样的 json 文件(到目前为止的共识和当前批次)作为字典一样多的内存,但是内存使用量随着每个批次线性增长,直到我最终耗尽内存。为什么会这样?当我将变量batch 设置为None 时,变量batch 引用的先前内容不应该被垃圾收集吗?

更新:所以我在每次循环迭代结束时添加了gc.collect(),内存仍然随着每次迭代线性增长。有什么想法吗?

【问题讨论】:

  • 你试过强制垃圾回收吗? stackoverflow.com/a/1316793/1042144
  • @BrianKung 这确实有助于阻止线性增长,但内存使用量仍会随着时间的推移而增加。
  • 不幸的是,我并不是特别擅长内存管理,Python 也不是我的主要语言。也许可以围绕它进行一些检测,然后在 Python 中查找内存优化技术。祝你好运!
  • 了解问题被否决的原因会很有帮助,这样我就可以增加获得有用答案的机会。

标签: python memory garbage-collection out-of-memory


【解决方案1】:

我相信你现在已经弄清楚了,但是我最近遇到了类似的问题,我很难找到答案。所以在这里发布我的解决方案以作记录。

大文件上的json.load()(或loads())似乎阻止了batch由于某些引用而被垃圾收集,因此您会遇到严重的内存泄漏。

然而,使batch 成为 json.load() 的深层副本似乎允许 python 正确运行垃圾收集。所以:

import copy
...
batch = copy.deepcopy(json.load(json_file))
...
gc.collect()

没有时间研究为什么会发生这种情况,但在我的情况下似乎有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-30
    • 1970-01-01
    • 1970-01-01
    • 2013-04-25
    • 2012-04-30
    • 2020-09-19
    • 2011-02-26
    • 2012-06-12
    相关资源
    最近更新 更多