我有一個包含大量對象的程序,其中很多是Numpy數組。我的程序更換悲慘,我試圖減少內存使用,因爲它實際上不能滿足當前內存要求我的系統。Python中的配置文件內存分配(支持Numpy數組)
我在尋找一個不錯的分析器,它可以讓我檢查各種對象消耗的內存量(我想象的是與cProfile相對應的內存),以便我知道在哪裏進行優化。
我聽說過關於Heapy的體面的事情,但Heapy不幸地不支持Numpy數組,而我的大部分程序都涉及Numpy數組。
我有一個包含大量對象的程序,其中很多是Numpy數組。我的程序更換悲慘,我試圖減少內存使用,因爲它實際上不能滿足當前內存要求我的系統。Python中的配置文件內存分配(支持Numpy數組)
我在尋找一個不錯的分析器,它可以讓我檢查各種對象消耗的內存量(我想象的是與cProfile相對應的內存),以便我知道在哪裏進行優化。
我聽說過關於Heapy的體面的事情,但Heapy不幸地不支持Numpy數組,而我的大部分程序都涉及Numpy數組。
當你不使用它們的時候,你可以在tmp文件中保存/ pickle一些數組到磁盤嗎?這就是我在過去使用大型陣列所必須做的事情。當然,這會減慢程序速度,但至少它會完成。除非你一次都需要它們?
好的,但是分析的要點是我想知道哪些數組我應該寫入文件。如果我試圖寫出所有內容並僅在需要時纔將其拉出,那麼I/O需求將非常龐大,並且會打敗這一點。 – chimeracoder 2010-07-30 18:14:41
看看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問了這個問題。
https://github.com/fabianp/memory_profiler/issues/9(「調用函數兩次時出現錯誤的結果」)似乎使它成爲任何嚴重應用程序的非啓動器。我誤解了這個問題嗎? – 2013-10-09 02:34:35
@WickedGrey也許你是對的,我從來沒有使用過'memory_profiler',只是瞭解它,但我現在可以重現這個錯誤。更新了我的答案。 – bmu 2013-10-11 05:37:57
由於memory_profiler查詢操作系統是否有足夠的內存使用,所以在不同的運行中不太可能會有稍微不同的結果,因爲這可能會被諸如IPython歷史或Python分配內存的方式所污染(您永遠不知道)當該內存被釋放時)。因此,結果的差異小於1%對我來說似乎不太可能。 – 2013-10-11 06:47:42
如果您正在調用許多不同的功能,並且您不確定從哪裏進行交換,則可以使用memory_profiler中的新繪圖功能來解決該問題。首先,您必須用@profile修飾您正在使用的不同功能。爲簡單起見,我將使用一個包含兩個功能隨memory_profiler的例子examples/numpy_example.py:create_data()
和process_data()
運行腳本,而不是用Python解釋器運行它,您可以使用mprof可執行文件,即
$ mprof run examples/numpy_example.py
這將創建一個名爲mprofile_??????????.dat
的文件,其中的?將持有代表當前日期的數字。要繪製的結果,只需輸入mprof plot
,它會產生一個類似的陰謀(如果有多個.dat文件將始終以最後一個):
這裏你可以看到內存消耗,括號表示何時進入/離開當前功能。通過這種方式,很容易看出功能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分配大量內存。
您是否試過valgrind
與massif
工具?
valgrind --tool=massif python yourscript.py
它會創建一個文件名爲massif.out.xxx
您可以通過
ms_print massif.out.xxx | less
它有各種有用的信息進行檢查,但情節就在一開始應該是你在找什麼。還可以在valgrind主頁上查看massif tutorial。
使用valgrind
是相當先進的,可能有更簡單的方法來做你想要的。
由於numpy的1.7存在內置的方式來跟蹤內存分配半:
https://github.com/numpy/numpy/tree/master/tools/allocation_tracking
神聖的廢話,這是超級有用的。謝謝!我有一個功能,其最大內存使用量與其輸入數據的大小相乘12倍。但是,現在,感謝那個'track_allocations.py'腳本,我將它降低到了4倍,所以我不會再看到那些煩人的'MemoryError'。唷!可愛的,現在在我的工具箱中。 – 2016-01-11 07:39:19
不是你(好)的問題,當然你可以使用大量的D型= np.float32 /的。 astype(np.float32)爲32位而不是64位浮點數。 (小心那些默默地做32英寸 - > 64輸出的函數) – denis 2010-08-01 10:36:24