【问题标题】:Out of Memory Killer activated for python script running a multiprocessing Queue?为运行多处理队列的python脚本激活了内存不足杀手?
【发布时间】:2014-03-31 04:41:04
【问题描述】:

我编写了一个 python 程序,需要一次运行多天,因为不断收集数据。以前我一次运行这个程序几个月都没有问题。我最近对程序进行了一些更新,现在大约 12 小时后,我得到了可怕的内存不足杀手。 'dmesg' 输出如下:

[9084334.914808] Out of memory: Kill process 2276 (python2.7) score 698 or sacrifice child
[9084334.914811] Killed process 2276 (python2.7) total-vm:13279000kB, anon-rss:4838164kB, file-rss:8kB

除了一般的 python 编码之外,对程序所做的主要更改是添加了一个多处理队列。这是我第一次使用这个功能,所以我不确定这是否是问题的原因。我的程序中队列的目的是能够在并行过程中进行动态更改。队列在主程序中启动,并在并行过程中不断受到监控。下面是我如何在并行过程中执行此操作的简化版本('q' 是队列):

while(1):

    if q.empty():
        None

    else:
        fr = q.get()
        # Additional code

    time.sleep(1)

'q' 的动态更改不会经常发生,因此大部分时间 q.empty() 将是真的,但是一旦进行更改,循环就会准备好。我的问题是,一次运行此代码多个小时会导致内存最终耗尽吗?由于'while'循环非常短并且基本上不间断地运行,我认为这可能是一个问题。如果这可能是问题的原因,是否有人对如何改进代码以使内存不足杀手不被调用有任何建议?

非常感谢。

【问题讨论】:

  • if q.empty(): pass 是编写该块的惯用方式。但最好只使用if not q.empty(): fr = q.get()
  • 你使用的是什么实现? .get() 是从队列中删除元素还是只检查它?在后一种情况下,队列的大小是单调递增的。
  • 您是否启用了交换? free 的输出是什么?
  • 感谢所有 cmets。我使用 .get() 的方式是从队列中删除一个列表。所以我在主程序中使用 .put() 将列表发送到并行进程,而 .get() 是它的选择。我之前假设输入.get()后,队列被清除,但也许我错了。
  • 我前段时间停止运行程序,但这里是 'free' 的当前输出:total used free shared buffers cached Mem: 8177396 1659060 6518336 0 255036 560160 -/+ buffers/cache: 843864 7333532 交换:10027004 869020 9157984

标签: python queue out-of-memory multiprocessing kill-process


【解决方案1】:

您描述的内存不足的唯一方法是随着时间的推移使用越来越多的内存。这里的循环演示了这种行为,因此它不能(单独)对任何内存错误负责。运行一个紧密的无限循环会消耗大量不必要的处理器周期,但它本身不会导致MemoryError,除非它将数据存储到其他地方。

很可能在您的代码的其他地方,您保留了一些您不打算保留的变量。这称为内存泄漏,您可以使用memory profiler 查找此类泄漏的来源。

一些可能的嫌疑人是用于提高性能的缓存方法,或者永远不会离开范围的变量列表。也许您的多处理队列正在保留对早期数据对象的引用,或者一旦插入项目就永远不会从队列中删除? (如果您使用内置 queue.Queue,鉴于您显示的代码,后一种情况不太可能发生,但一切皆有可能)。

【讨论】:

  • 这不是答案。发表评论。
  • @Stefano 这怎么不是答案? "My question is, would running this code for multiple hours at a time cause the memory to eventually run low?" 答案是否定的,给定的代码不会导致程序内存不足。
  • 您的回答如下:我无法断定您的代码本身会导致此错误,请提供更多详细信息。这就是我要发表的评论。而那段(伪)代码很可能是原因,因为你不知道queue.get 的行为。
  • @Stefano 由于缺乏其他信息,我假设他正在使用queue.Queue,这不会导致这种行为。提问者没有要求我们查找内存泄漏,而是是否可能由并行进程中的紧密循环引起。不过,我已经编辑了我的答案,希望不像请求更多信息那样阅读。
  • 问题不限于循环," 一次运行此代码会导致内存最终耗尽吗?"。而且,程序员应该提防假设。如有疑问,请咨询 OP。
【解决方案2】:

您可以将您的程序转换为 linux 服务并将其 oom 策略设置为继续。

您可以查看thisthis 链接,分别查看如何查看/编辑服务参数和查看oom policy 服务参数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-20
    • 2014-01-11
    • 2015-04-20
    • 1970-01-01
    • 1970-01-01
    • 2015-09-04
    相关资源
    最近更新 更多