2010-07-30 113 views
26

我有一個包含大量對象的程序,其中很多是Numpy數組。我的程序更換悲慘,我試圖減少內存使用,因爲它實際上不能滿足當前內存要求我的系統。Python中的配置文件內存分配(支持Numpy數組)

我在尋找一個不錯的分析器,它可以讓我檢查各種對象消耗的內存量(我想象的是與cProfile相對應的內存),以便我知道在哪裏進行優化。

我聽說過關於Heapy的體面的事情,但Heapy不幸地不支持Numpy數組,而我的大部分程序都涉及Numpy數組。

+0

不是你(好)的問題,當然你可以使用大量的D型= np.float32 /的。 astype(np.float32)爲32位而不是64位浮點數。 (小心那些默默地做32英寸 - > 64輸出的函數) – denis 2010-08-01 10:36:24

回答

0

當你不使用它們的時候,你可以在tmp文件中保存/ pickle一些數組到磁盤嗎?這就是我在過去使用大型陣列所必須做的事情。當然,這會減慢程序速度,但至少它會完成。除非你一次都需要它們?

+3

好的,但是分析的要點是我想知道哪些數組我應該寫入文件。如果我試圖寫出所有內容並僅在需要時纔將其拉出,那麼I/O需求將非常龐大,並且會打敗這一點。 – chimeracoder 2010-07-30 18:14:41

10

看看memory profiler。它通過在線分析和Ipython整合,這使得它非常容易使用,它提供行:似乎是一個錯誤

In [1]: import numpy as np 

In [2]: %memit np.zeros(1e7) 
maximum of 3: 70.847656 MB per loop 

更新

正如@WickedGrey提到的(see github issue tracker)調用時功能超過一次,我可以重現:

In [2]: for i in range(10): 
    ...:  %memit np.zeros(1e7) 
    ...:  
maximum of 1: 70.894531 MB per loop 
maximum of 1: 70.894531 MB per loop 
maximum of 1: 70.894531 MB per loop 
maximum of 1: 70.894531 MB per loop 
maximum of 1: 70.894531 MB per loop 
maximum of 1: 70.894531 MB per loop 
maximum of 1: 70.902344 MB per loop 
maximum of 1: 70.902344 MB per loop 
maximum of 1: 70.902344 MB per loop 
maximum of 1: 70.902344 MB per loop 

但是我不知道什麼擴展的結果可能影響(似乎沒有那麼多在我的例子,所以德等待你的用例,它可能仍然有用),並且當這個問題可能修復。我在github問了這個問題。

+0

https://github.com/fabianp/memory_profiler/issues/9(「調用函數兩次時出現錯誤的結果」)似乎使它成爲任何嚴重應用程序的非啓動器。我誤解了這個問題嗎? – 2013-10-09 02:34:35

+0

@WickedGrey也許你是對的,我從來沒有使用過'memory_profiler',只是瞭解它,但我現在可以重現這個錯誤。更新了我的答案。 – bmu 2013-10-11 05:37:57

+0

由於memory_profiler查詢操作系統是否有足夠的內存使用,所以在不同的運行中不太可能會有稍微不同的結果,因爲這可能會被諸如IPython歷史或Python分配內存的方式所污染(您永遠不知道)當該內存被釋放時)。因此,結果的差異小於1%對我來說似乎不太可能。 – 2013-10-11 06:47:42

11

如果您正在調用許多不同的功能,並且您不確定從哪裏進行交換,則可以使用memory_profiler中的新繪圖功能來解決該問題。首先,您必須用@profile修飾您正在使用的不同功能。爲簡單起見,我將使用一個包含兩個功能隨memory_profiler的例子examples/numpy_example.pycreate_data()process_data()

運行腳本,而不是用Python解釋器運行它,您可以使用mprof可執行文件,即

$ mprof run examples/numpy_example.py 

這將創建一個名爲mprofile_??????????.dat的文件,其中的?將持有代表當前日期的數字。要繪製的結果,只需輸入mprof plot,它會產生一個類似的陰謀(如果有多個.dat文件將始終以最後一個):

output of memory_profiler's mprof

這裏你可以看到內存消耗,括號表示何時進入/離開當前功能。通過這種方式,很容易看出功能process_data()的內存消耗峯值爲 。爲了進一步深入您的功能,您可以使用逐行分析器來查看函數中每行的內存消耗。這與

python -m memory_profiler examples/nump_example.py 

運行時,這會給你類似這樣的輸出:

Line # Mem usage Increment Line Contents 
================================================ 
    13        @profile 
    14 223.414 MiB 0.000 MiB def process_data(data): 
    15 414.531 MiB 191.117 MiB  data = np.concatenate(data) 
    16 614.621 MiB 200.090 MiB  detrended = scipy.signal.detrend(data, axis=0) 
    17 614.621 MiB 0.000 MiB  return detrended 

它顯然是scipy.signal.detrend分配大量內存。

0

您是否試過valgrindmassif工具?

valgrind --tool=massif python yourscript.py 

它會創建一個文件名爲massif.out.xxx您可以通過

ms_print massif.out.xxx | less 

它有各種有用的信息進行檢查,但情節就在一開始應該是你在找什麼。還可以在valgrind主頁上查看massif tutorial

使用valgrind是相當先進的,可能有更簡單的方法來做你想要的。

1

由於numpy的1.7存在內置的方式來跟蹤內存分配半:

https://github.com/numpy/numpy/tree/master/tools/allocation_tracking

+1

神聖的廢話,這是超級有用的。謝謝!我有一個功能,其最大內存使用量與其輸入數據的大小相乘12倍。但是,現在,感謝那個'track_allocations.py'腳本,我將它降低到了4倍,所以我不會再看到那些煩人的'MemoryError'。唷!可愛的,現在在我的工具箱中。 – 2016-01-11 07:39:19