我有大量的數據文件,並且從數據文件加載的每個數據都被重新採樣數百次,並通過多種方法進行處理。我用numpy
來做到這一點。我所面對的是運行程序幾個小時後的內存錯誤。由於每個數據分開處理,並將結果保存在一個文件.mat
使用scipy.savemat
,我認爲以前的數據所使用的內存可以被釋放,所以我用del variable_name
+ gc.collect()
,但這不起作用。然後我用multiprocessing
模塊,如仍處於this post和this post建議,它不工作。如何在Python中有效釋放內存?
這裏是我的主要代碼:
import scipy.io as scio
import gc
from multiprocessing import Pool
def dataprocess_session:
i = -1
for f in file_lists:
i += 1
data = scio.loadmat(f)
ixs = data['rm_ix'] # resample indices
del data
gc.collect()
data = scio.loadmat('xd%d.mat'%i) # this is the data, and indices in "ixs" is used to resample subdata from this data
j = -1
mvs_ls_org = {} # preallocate results files as dictionaries, as required by scipy.savemat.
mvs_ls_norm = {}
mvs_ls_auto = {}
for ix in ixs:
j += 1
key = 'name%d'%j
X = resample_from_data(data,ix)
mvs_ls_org[key] = process(X)
scio.savemat('d%d_ls_org.mat'%i,mvs_ls_org)
del mvs_ls_org
gc.collect()
j = -1
for ix in ixs:
j += 1
key = 'name%d'%j
X = resample_from_data(data,ix)
X2 = scale(X.copy(), 'norm')
mvs_ls_norm[key] = process(X2)
scio.savemat('d%d_ls_norm.mat'%i,mvs_ls_norm)
del mvs_ls_norm
gc.collect()
j = -1
for ix in ixs:
j += 1
key = 'name%d'%j
X = resample_from_data(data,ix)
X2 = scale(X.copy(), 'auto')
mvs_ls_auto[key] = process(X2)
scio.savemat('d%d_ls_auto.mat'%i,mvs_ls_auto)
del mvs_ls_auto
gc.collect()
# use another method to process data
j = -1
mvs_fcm_org = {} # also preallocate variable for storing results
mvs_fcm_norm = {}
mvs_fcm_auto = {}
for ix in ixs:
j += 1
key = 'name%d'%j
X = resample_from_data(data['X'].copy(), ix)
dp, _ = process_2(X.copy())
mvs_fcm_org[key] = dp
scio.savemat('d%d_fcm_org.mat'%i,mvs_fcm_org)
del mvs_fcm_org
gc.collect()
j = -1
for ix in ixs:
j += 1
key = 'name%d'%j
X = resample_from_data(data['X'].copy(), ix)
X2 = scale(X.copy(), 'norm')
dp, _ = process_2(X2.copy())
mvs_fcm_norm[key] = dp
scio.savemat('d%d_fcm_norm.mat'%i,mvs_fcm_norm)
del mvs_fcm_norm
gc.collect()
j = -1
for ix in ixs:
j += 1
key = 'name%d'%j
X = resample_from_data(data['X'].copy(), ix)
X2 = scale(X.copy(), 'auto')
dp, _ = process_2(X2.copy())
mvs_fcm_auto[key] = dp
scio.savemat('d%d_fcm_auto.mat'%i,mvs_fcm_auto)
del mvs_fcm_auto
gc.collect()
這是最初的方式,我已經做到了。我將file_lists
分成7部分,並運行7個python屏幕,因爲我的電腦有8個CPU核心。 如果我這樣做,MATLAB中沒有問題。我不超過ixs
結合迭代每個數據處理方法,因爲可能會出現內存不足的錯誤,所以我跑resample_from_data
並單獨保存的結果。由於內存錯誤仍然存在,我用Pool
類爲:
pool = Pool(processes=7)
pool.map(dataprocess_session_2, file_lists)
跑在file_lists
文件名作爲輸入並行過file_lists
迭代。
所有代碼在openSuSE
中運行,其中python 2.7.5
,8 cores CPU
和32G RAM
。我用top
來監視使用的內存。所有的矩陣都不是很大,如果我使用所有代碼運行任何一個加載的數據,那也沒關係。但經過file_lists
的多次迭代後,可用內存急劇下降。我確信這種現象不是由數據本身引起的,因爲即使是最大的數據矩陣處理中也不應該使用這樣大的存儲器。所以我懷疑上述的方式我試圖釋放處理以前的數據使用的內存以及存儲處理結果並沒有真正釋放內存。
有什麼建議嗎?
爲什麼我被低估了? – Elkan
我真的需要自己仔細閱讀這篇文章,但我認爲你不能用這種方式強迫'gc'的手。 Python使用引用計數來決定是否刪除對象,所以'gc.collect()'可能不會立即刪除這些對象。如果你想把每個循環分解成不返回數據的函數,你可能會有更多的希望,但是你應該只是把這個作爲一個輔助手段來進一步閱讀python gc,因爲我可以做得更好那個建議。希望有更多的知識能夠澄清。 – roganjosh
更新你的建議:我現在正在嘗試,雖然沒有發生錯誤,但是在運行這兩天的數據集後,只剩幾KB的內存(與我的PC的32G RAM相比)是空閒的。由於處理的數據體積相對較小,恐怕如果以這種方式使用,內存仍然可能會耗盡。 – Elkan