我正在做一些生物信息学工作。我有一个python脚本,它一度调用程序来执行一个昂贵的过程(序列对齐......使用大量的计算能力和内存)。我用subprocess.Popen调用它。当我在测试用例上运行它时,它完成并完成。但是,当我在完整文件上运行它时,它必须多次为不同的输入集执行此操作,它会死掉。子流程抛出:
OSError: [Errno 12] Cannot allocate memory
我发现了一些链接here和here以及here来解决类似的问题,但我不确定它们是否适用于我的情况。
默认情况下,序列对齐器将尝试请求51000M的内存。它并不总是使用那么多,但它可能会。加载和处理完整输入后,就无法使用。但是,限制它请求的数量或将尝试使用的数量较少,在运行时可能仍然可用,这会给我带来同样的错误。我也试过用shell = True和同样的东西运行。
这已经困扰了我几天了。谢谢你的帮助。
编辑:扩展追溯:
File "..../python2.6/subprocess.py", line 1037, in _execute_child
self.pid=os.fork()
OSError: [Errno 12] Cannot allocate memory
抛出错误。
Edit2:在64位ubuntu 10.4上运行python 2.6.4
答案 0 :(得分:5)
我对OP感到非常抱歉。 6年后,没有人提到这是Unix中一个非常普遍的问题,实际上与python或生物信息学无关。对os.fork()的调用会暂时将父进程的内存加倍(父进程的内存必须对子进程可用),然后将其全部丢弃以执行exec()。虽然这个内存并不总是被实际复制,但是系统必须有足够的内存来允许它被复制,因此如果你的父进程使用了超过一半的系统内存并且你甚至“wc -l”进行了子处理“,你会遇到内存错误。
解决方案是使用posix_spawn,或者在脚本开头创建所有子进程,同时内存消耗很低,然后在父进程完成内存密集之后再使用它们。
使用keyworks“os.fork”和“memory”的谷歌搜索将显示该主题的几个Stack Overflow帖子,可以进一步解释发生了什么:)
答案 1 :(得分:0)
我在64位操作系统上运行64位python。
使用32位,在操作系统开始告诉你之前,你只能获得3 GB的RAM。
另一种选择可能是使用内存映射文件来打开文件:
http://docs.python.org/library/mmap.html
编辑:啊,你是64位...可能原因是你的RAM +交换耗尽..修复可能会增加交换量。
答案 2 :(得分:0)
这与Python或subprocess
模块无关。 subprocess.Popen
仅向您报告它从操作系统收到的错误。 (顺便说一句,您使用的操作系统是什么?)来自Linux上的man 2 fork
:
ENOMEM fork() failed to allocate the necessary kernel structures
because memory is tight.
您是否多次致电subprocess.Popen
?如果是这样,那么我认为您可以做的最好的事情是确保在下次调用之前终止并重新获取您的进程的先前调用。
答案 3 :(得分:0)
你使用subprocess.PIPE吗?我遇到问题,并在使用时了解问题。临时文件通常可以解决问题。