【发布时间】:2022-10-08 22:31:57
【问题描述】:
我在带有数字标签的文件夹中有一组文件,我正在尝试整理和提取包含数据的统计信息。我的最小代码是:
import psutil as psutil
import sys as sys
import pandas as pd
import os as os
import glob as glob
import numpy as np
import matplotlib.pyplot as plt
@profile
def main():
temp=[]
strj=pd.DataFrame()
ener_list=[]
ref_ener_list=[]
main_dir="./"
column_list=["1","2","3","4","5","6","7"]
f1_list=["part1","part2"]
for folder in sorted(glob.iglob(main_dir+"/0????")):
print(folder)
print(psutil.Process().memory_info().rss / (1024 * 1024))
for fld2 in sorted(glob.iglob(folder+"/run?????")):
strj=pd.DataFrame()
for fld1 in f1_list:
for data_file in sorted(glob.iglob(fld2+"/prdv"+fld1+"/track.txt")):
temp=pd.read_table(data_file, comment="#",delim_whitespace=True,names=column_list)
strj=pd.concat([strj, temp])
del(temp)
ener_list.append(strj.values.tolist())
del(strj)
print(np.shape(ener_list))
avg_ener_list=(np.array(ener_list,dtype=object)).mean(axis=0)
avg_ener_df=pd.DataFrame(avg_ener_list, columns=column_list)
print(avg_ener_df,np.shape(avg_ener_df))
main()
exit()
对于整个数据集,我有 50 个文件夹和 1000 个子文件夹,每个子文件夹有 2 个部分。单个文件的大小可以是 5.6Kb(小)或 320Kb(大)。当我尝试在所有文件夹上运行我的代码时,我注意到我使用了超过 28GB 的内存,导致程序在数据提取部分进行到一半时被终止。我使用 memory_profiler 工具来跟踪内存泄漏,但我无法真正弄清楚我需要进行哪些更改。我在这种情况下缺乏经验,因为我以前不必处理内存问题。我也尝试跟踪变量使用的内存,但那里没有什么奇怪的。我在这里忽略了其他一些方面,还是应该改变我在这里提取数据的方式?
Line # Mem usage Increment Occurrences Line Contents
=============================================================
23 99.961 MiB 99.961 MiB 1 @profile
24 def main():
25 99.961 MiB 0.000 MiB 1 temp=[]
26 99.961 MiB 0.000 MiB 1 strj=pd.DataFrame()
27
28 99.961 MiB 0.000 MiB 1 ener_list=[]
29 99.961 MiB 0.000 MiB 1 ref_ener_list=[]
30 99.961 MiB 0.000 MiB 1 main_dir="./"
31 99.961 MiB 0.000 MiB 1 column_list=["Step","Time","KE","Temp", "PE","TE","UsedTime"]
32 #f_list=["part1","part2","part3"]
33 99.961 MiB 0.000 MiB 1 f1_list=["part1","part2"]
34 99.961 MiB 0.000 MiB 1 f2_list=["part1"]
35
36
37 8065.902 MiB 0.000 MiB 10 for folder in sorted(glob.iglob(main_dir+"/0????")):
38 7181.180 MiB 0.000 MiB 9 print(folder)
39 7181.180 MiB 0.000 MiB 9 print(psutil.Process().memory_info().rss / (1024 * 1024))
40 8065.902 MiB -0.527 MiB 9009 for fld2 in sorted(glob.iglob(folder+"/run?????")):
41 8065.020 MiB -0.527 MiB 9000 strj=pd.DataFrame()
42 8065.133 MiB -4.262 MiB 27000 for fld1 in f1_list:
43 8065.133 MiB -3.449 MiB 36000 for data_file in sorted(glob.iglob(fld2+"/prdv"+fld1+"/track.txt")):
44 #pass
45 8066.078 MiB 9237.312 MiB 18000 temp=pd.read_table(data_file, comment="#",delim_whitespace=True,names=column_list)
46 8066.078 MiB -8199.547 MiB 18000 strj=pd.concat([strj, temp])
47 8065.133 MiB -16399.094 MiB 18000 del(temp)
48 #strj=pd.concat([strj, pd.read_table(data_file, comment="#",delim_whitespace=True,names=column_list)])
49 #temp.append(pd.read_csv(data_file, delim_whitespace=True, skiprows=1))
50 8065.902 MiB 6923.656 MiB 9000 ener_list.append(strj.values.tolist())
51 8065.902 MiB -0.270 MiB 9000 del(strj)
52 #print(sys.getsizeof(strj)/(1024*1024), sys.getsizeof(ener_list)/(1024*1024))
53 #print(ener_list,np.shape(ener_list))
54 8067.801 MiB 1.898 MiB 1 print(np.shape(ener_list))
55
56 8067.926 MiB 0.125 MiB 1 avg_ener_list=(np.array(ener_list,dtype=object)).mean(axis=0)
57 8067.926 MiB 0.000 MiB 1 avg_ener_df=pd.DataFrame(avg_ener_list, columns=column_list)
58
59 8068.469 MiB 0.543 MiB 1 print(avg_ener_df,np.shape(avg_ener_df))
【问题讨论】:
-
@metatoaster 我尝试使用 gc.collect() 但我没有看到内存使用有任何重大变化。相反,相同大小的数据集的运行时间显着增加,代码变得不可用。同样在链接线程中,主要问题是显式调用 gc.collect() 通常不会提供任何重大更改。
-
好吧,问题之一是
ener_list将随着您的代码读取更多文件而继续增长(并消耗内存),并且“临时”数据上的所有del不太可能对您的情况有所帮助。尝试像这样注释掉所有相关的append以查看是否只是处理输入文件会导致问题,但如果您需要显式内存管理 Python 不是要使用的语言。 -
@metatoaster 注释掉
append部分确实消除了内存问题并将使用的内存减少到 <5MiB。但奇怪的是ener_list的大小只有 0.072 KiB(使用 getsizeof()),而 psutils 显示内存使用量高达 8GiB!所以我不确定多余的内存在哪里被使用...... -
ener_list引用了strj内部的某些东西(通过strj.values.tolist()),这可能与原始内容有某种联系,从而使 numpy/pandas 内部的引用计数不被减少?搜索tolist内存问题我遇到了this thread,所以可能是tolist是内存泄漏的罪魁祸首。
标签: python memory memory-leaks profiling