2017-01-09 59 views
3

我在Ubuntu 16.10上使用numpy(1.13.1)和pandas(0.20.3),使用python 2.7或3.5(兩者都有相同的問題)。熊貓使用大量更多的內存用於存儲比要求

我正在研究熊貓記憶處理(特別是當它複製或不復制數據)並遇到了我不明白的重大記憶問題。雖然我已經看到(很多)人們關於其內存性能的其他問題,但我還沒有發現任何直接解決此問題的方法。

具體而言,熊貓分配lot更多的內存比我問它。我注意到,當只是想分配一個數據幀具有特定大小的列了一些非常奇怪的現象:

import pandas as pd, numpy as np 
GB = 1024**3 
df = pd.DataFrame() 
df['MyCol'] = np.ones(int(1*GB/8), dtype='float64') 

當我執行此我看到我的蟒蛇過程實際上分配6GB內存,(12G如果我問了2GB ,如果我要求3GB,則爲21GB,如果我要求4GB,則計算機會中斷: - /),而不是預期的1GB。我首先想到的可能是Python正在進行一些積極的預分配,但是如果我只是自己構建numpy數組,我會得到我每次要求的內存量,無論是1GB,10GB,25GB,無論如何。

此外,什麼是更有趣的是,如果我稍微改變代碼如下:

df['MyCol'] = np.ones(int(1*GB), dtype='uint8') 

它分配這麼多的內存崩潰我的系統(單獨運行numpy的呼叫正確地分配1GB內存)。 (編輯2017/8/17:出於好奇,我今天嘗試使用更新版本的熊貓(0.20.3)和numpy(1.13.1),並將RAM升級到64GB,並且運行此命令仍然失敗,分配所有64(ISH)GB可用RAM的。)

我能理解加倍,甚至三倍問,如果大熊貓進行復印,也許是內存的分配另一列存儲索引,但我不能解釋它實際上在做什麼。粗略瀏覽代碼也不完全清楚。

我試着以幾種不同的方式構建數據框,所有的結果都一樣。鑑於其他人成功地使用這個軟件包進行大數據分析,我必須假定我正在做一些可怕的錯誤,儘管從我能告訴給出的文檔應該是正確的。

想法?

一些附加註釋:

  1. 即使當存儲器使用率大,熊貓仍然(錯誤地),如果我分配一個1GB陣列它報告1GB報告時memory_usage()被調用所期望的數據大小(即,即使實際分配了6-10GB)。
  2. 在所有情況下,索引都很小(由mem​​ory_usage()報告,這可能不準確)。
  3. 取消分配大熊貓DataFrame(df = None,gc.collect())實際上並不釋放所有內存。使用這種方法必定會有泄漏。
+1

嘗試此代替:'DF = pd.DataFrame({ 'MyCol':np.ones(INT(1 * GB), dtype = np.uint8)})' – MaxU

+1

@MaxU雖然這樣表現更好,但它仍然不夠完美。有一個很大的開銷(對象的大小的100%,多一點),得到分配(我認爲這是製作一份數據的副本)。這似乎有比我的例子中更多似是而非的解釋,但如果我不幸地需要拋出超過15GB的內存,這並沒有幫助。 (注意:即使數據被分割到多個通道上,也會發生這種情況,例如,3個5GB通道需要使用此方法分配近30GB的數據,因此如果正在創建數據副本,則不會將其釋放,直到最後纔會釋放它們。) – Anthony

+0

df.index佔用了多少空間?如果添加另一列,可能是相同的'np.array',內存如何使用更改? – hpaulj

回答

0

所以我做一個8000字節數組:

In [248]: x=np.ones(1000) 

In [249]: df=pd.DataFrame({'MyCol': x}, dtype=float) 
In [250]: df.info() 
<class 'pandas.core.frame.DataFrame'> 
Int64Index: 1000 entries, 0 to 999 
Data columns (total 1 columns): 
MyCol 1000 non-null float64 
dtypes: float64(1) 
memory usage: 15.6 KB 

這樣8K的數據和8K的索引。

我添加列 - 通過x大小使用率增加:

In [251]: df['col2']=x 
In [252]: df.info() 
<class 'pandas.core.frame.DataFrame'> 
Int64Index: 1000 entries, 0 to 999 
Data columns (total 2 columns): 
MyCol 1000 non-null float64 
col2  1000 non-null float64 
dtypes: float64(2) 
memory usage: 23.4 KB 

In [253]: x.nbytes 
Out[253]: 8000 
+0

我用一些筆記更新了我的問題。即使實際分配了更多(例如6GB),Pandas也會報告預期的內存使用率(例如,如果我創建1GB陣列,則報告1GB)。當對象被銷燬並且垃圾收集器被運行時,它也沒有釋放所有分配的內存,這讓我相信在熊貓中可能會有內存泄漏。 – Anthony

+0

因此,您更關心一路上的內存使用情況,而不是最終用法。我不知道如果你製作numpy數組會發生什麼,然後複製一個加上相同大小的'np.arange()'(索引數組)。換句話說,嘗試創建相同的最終numpy數組,但沒有'df'結構。 – hpaulj

+0

兩者,但這是「最終」用法。 DataFrame可能只有1GB,但如果分配的內存總量(仍然是分配的,不是在構建對象的過程中使用的)增加了6倍,那真是一個問題。另外,在使用uint8分配1GB進行初始化的情況下注意事實上會炸燬我的內存(32GB)並崩潰。這些都是問題。正如在構建post後所提到的那樣,numpy數組本身沒有問題,只把它放到一個數據框中。 – Anthony