2011-03-15 143 views
4

我正在做一些生物信息學工作。我有一個python腳本,它在某個時刻調用一個程序來執行一個昂貴的過程(序列對齊......使用大量的計算能力和內存)。我使用subprocess.Popen調用它。當我在一個測試用例上運行它時,它會完成並完成正常工作。但是,當我在完整文件上運行它時,它將不得不多次爲不同的輸入集執行此操作,它會死亡。子拋出:使用子進程的Python內存分配錯誤.Popen

OSError: [Errno 12] Cannot allocate memory 

我發現幾個環節hereherehere類似的問題,但我不知道他們在我的情況適用。

默認情況下,序列對齊器將嘗試請求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

+0

你能在獨立模式下執行程序子,從命令行?你可以啓動幾個實例將它們設置爲背景(使用'&終止命令)?如何運行'time -v foo ...'來獲得關於程序使用計算機資源的一些統計信息? – Apalala 2011-03-16 14:16:13

回答

0

運行在Python 2.6.4我會運行在64位操作系統64位蟒蛇。

使用32位,在操作系統啓動之前,你只能真正獲得3 GB的RAM,不再告訴你。

另一種方法是使用內存映射文件來打開文件:

http://docs.python.org/library/mmap.html

編輯:啊你是在64位..可能的原因是,你用完了的RAM +交換..修復將是增加交換量可能。

+0

我在兩端運行64位。使用內存映射文件和普通文件有什麼優勢? – jmerkin 2011-03-15 13:36:08

+0

一個好處是您可以告訴操作系統針對隨機或順序訪問進行優化,並且可以打開並分塊大於RAM的文件。 – matiu 2011-04-26 23:37:56

+0

內存映射文件的缺點是,如果您的機器意外停機,它們會非常脆弱。 – matiu 2011-04-26 23:39:01

0

這與Python或subprocess模塊沒有任何關係。 subprocess.Popen只是向您報告它從操作系統收到的錯誤。 (什麼操作系統您使用的,順便說一句?)從man 2 fork在Linux上:

ENOMEM fork() failed to allocate the necessary kernel structures 
      because memory is tight. 

你打電話subprocess.Popen多次?如果是這樣,那麼我認爲你可以做的最好的事情是確保先前的進程調用在下一次調用之前終止並獲得。

+0

我多次調用它,但接連不斷。我在那裏拋出一個subprocess.communicate(),因爲我需要每個的stdout。 – jmerkin 2011-03-15 13:35:09

+1

此外,如果這是內存不足,爲什麼不使用交換文件(該計算機是共享資源,並具有64克RAM,所以我認爲它沒有定義的交換空間)? – jmerkin 2011-03-15 13:58:38

+0

@jmerkin,使用'swapon -s'來判斷是否配置了交換,使用'free'告訴你有多少可用的物理內存和交換空間。如果您沒有交換,配置交換是增加可用虛擬內存的一種方式。另外,我建議你回答@Konstantin Tenzin的問題。你真的在使用子進程的結果(stdout/stderr)嗎?如果是這樣,結果很大嗎?如果是這樣,你在做什麼來確保你的Python進程不消耗所有可用的內存? – rlibby 2011-03-15 15:19:26

0

你使用subprocess.PIPE嗎?我遇到問題並在使用時發現問題。臨時文件通常可以解決問題。

+0

我已經嘗試過兩種方法。我嘗試直接寫入文件以及子流程.PIPE: a = subprocess.Popen('foo> bar',shell = True,stderr = subprocess.PIPE); a.wait()) a = subprocess.Popen(foo,stdout = subprocess。PIPE,stderr = subprocess.PIPE) f_out.write(a.communicate()[0]) 這也給了我這個錯誤。 Stderr相當可以忽略不計,關於該計劃的進展最多隻有幾行,所以它不應該太多。 – jmerkin 2011-03-15 16:00:49

4

我對OP感到非常抱歉。 6年後,沒有人提到這是Unix中的一個非常普遍的問題,實際上與Python或生物信息學無關。調用os.fork()暫時將父進程的內存加倍(父進程的內存必須可用於子進程),然後將其全部拋出以執行exec()。雖然這個內存並不總是被實際複製,但是系統必須有足夠的內存以允許它被複制,因此如果你的父進程使用了​​超過一半的系統內存,並且你可以進行子處理,即使是「wc -l 「,你會遇到內存錯誤。

解決方案是使用posix_spawn,或者在腳本的開始處創建所有子進程,而內存消耗較少,然後在父進程完成內存密集型事務後再使用它們。

使用的圖片關鍵詞「os.fork」和「記憶」谷歌搜索將顯示在該主題的幾個堆棧溢出職位,可以進一步解釋這是怎麼回事:)