如何在python中有效地释放内存?
我有大量的数据文件,从数据文件加载的每个数据都会被重新采样数百次,并通过多种方法进行处理。我用numpy来做这个。我面临的是运行程序几个小时后出现的内存错误。由于每个数据都是单独处理的,并且使用scipy.savemat将结果存储在.mat文件中,因此我认为可以释放以前数据使用的内存,因此我使用了del变量_name+gc.collect,但这不起作用。然后我使用了多处理模块,正如和中所建议的,它仍然不起作用 以下是我的主要代码:如何在python中有效地释放内存?,python,matlab,numpy,Python,Matlab,Numpy,我有大量的数据文件,从数据文件加载的每个数据都会被重新采样数百次,并通过多种方法进行处理。我用numpy来做这个。我面临的是运行程序几个小时后出现的内存错误。由于每个数据都是单独处理的,并且使用scipy.savemat将结果存储在.mat文件中,因此我认为可以释放以前数据使用的内存,因此我使用了del变量_name+gc.collect,但这不起作用。然后我使用了多处理模块,正如和中所建议的,它仍然不起作用 以下是我的主要代码: import scipy.io as scio import g
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()
这是我最初的做法。我将文件列表分为7部分,并运行了7个python屏幕,因为我的计算机有8个CPU核心。如果我这样做,在MATLAB中没有问题。对于每个数据处理方法,我不会将ixs上的迭代组合在一起,因为可能会发生内存错误,所以我从_数据运行了重采样_,并分别保存了结果。由于内存错误仍然存在,我将池类用作:
pool = Pool(processes=7)
pool.map(dataprocess_session_2, file_lists)
它在与文件列表中的文件名并行的文件列表上运行迭代作为输入
所有代码都在openSuSE中运行,带有python 2.7.5、8核CPU和32G RAM。我使用top来监视所使用的内存。所有的矩阵都不是那么大,如果我使用所有代码运行任何一个加载的数据也没关系。但是在对文件列表进行多次迭代之后,可用内存急剧下降。我确信这种现象不是由数据本身造成的,因为即使处理的是最大的数据矩阵,也不应该使用如此大的内存。因此,我怀疑,我试图通过上述方法释放用于处理先前数据以及存储处理结果的内存,但实际上并没有释放内存
有什么建议吗?这可能会有所帮助,gc。收集所有显式删除的变量将在循环结束后自动释放。后来我认为这不是你的问题。我认为更可能的情况是,您的机器无法处理7个线程,在最坏的情况下,7个线程同时执行data=scio.loadmatf。您可以尝试将该调用标记为带有锁的关键部分。我认为以前数据使用的内存可以释放,因此我使用了del variable_name+gc.collect,但这不起作用。为什么我被否决了?我自己确实需要仔细阅读,但我认为您无法以这种方式强制gc。Python使用引用计数来决定是否应该删除对象,因此gc.collect可能不会立即删除这些对象。如果您要将这些循环分解为它们自己的函数,而这些函数不返回数据,那么您可能会有更多的希望,但同样,您应该将此作为进一步阅读python gc的帮助,因为我可以很好地理解这一建议。希望有更了解情况的人能够澄清。更新您的建议:我现在正在尝试,虽然没有出现错误,但在运行我的数据集两天后,与我电脑的32G RAM相比,只有几KB的内存可用。由于处理后的数据相对较小,我担心如果这样使用,内存可能仍然会耗尽。谢谢。你能解释一下吗?任何7个数据同时加载到内存中都没有问题,所以机器不能处理7个线程和7个同时执行的数据=sco.loadmatf意味着什么?这不仅仅是7个数据。您需要考虑最坏的情况,即所有线程都在使用其最大内存量。我不能告诉你什么对象最大,你可以在单线程模式下最好地分析它们。我明白了。我使用MATLAB对相同的数据集做相同的工作,但使用了不同的处理方法,这是由我的python代码中的process函数指定的,甚至更多的都加载到MATLAB中的内存中,运行数天后不存在错误。因为我的矩阵不是那么大,返回的X和X2与原始矩阵大小相同,即使经过ixs迭代,仍然有很大的自由空间。这是由linux中的top监控的。我注意到python在del之后仍然保留免费列表,但我没有找到任何有效的解决方案。所以我怀疑我是否错过了什么。