cha*_*eno 8 python performance memory-management
我必须迭代地读取数据文件并将数据存储到(numpy)数组中.我选择将数据存储到"数据字段"字典中:{'field1':array1,'field2':array2,...}.
使用list(或collections.deque())来"追加"新数据数组,代码是高效的.但是,当我连接存储在列表中的数组时,内存会增长,而我却无法再次释放它.例:
filename = 'test'
# data file with a matrix of shape (98, 56)
nFields = 56
# Initialize data dictionary and list of fields
dataDict = {}
# data directory: each entry contains a list 
field_names = []
for i in xrange(nFields):
    field_names.append(repr(i))
    dataDict[repr(i)] = []
# Read a data file N times (it represents N files reading)
# file contains 56 fields of arbitrary length in the example
# Append each time the data fields to the lists (in the data dictionary)
N = 10000
for j in xrange(N):
    xy = np.loadtxt(filename)
    for i,field in enumerate(field_names):
        dataDict[field].append(xy[:,i])
# concatenate list members (arrays) to a numpy array 
for key,value in dataDict.iteritems():
    dataDict[key] = np.concatenate(value,axis=0)
Run Code Online (Sandbox Code Playgroud)
计算时间:   63.4秒
内存使用量(上):13862 gime_se 20 0 1042m  934m 4148 S 0 5.8 1:00.44 python
每次加入时直接连接numpy数组,效率低下但内存仍然受到控制.例:
nFields = 56
dataDict = {}
# data directory: each entry contains a list 
field_names = []
for i in xrange(nFields):
    field_names.append(repr(i))
    dataDict[repr(i)] = np.array([])
# Read a data file N times (it represents N files reading)
# Concatenate data fields to numpy arrays (in the data dictionary)
N = 10000
for j in xrange(N):
    xy = np.loadtxt(filename)
    for i,field in enumerate(field_names):
        dataDict[field] = np.concatenate((dataDict[field],xy[:,i])) 
Run Code Online (Sandbox Code Playgroud)
计算时间:   1377.8秒
内存使用量(上):14850 gime_se 20 0 650m  542m 4144 S 0 3.4 22:31.21 python
是否有任何方法可以获得案例1的性能,但是如案例2那样保持内存的控制?
似乎在情况1中,当连接列表成员(np.concatenate(value,axis = 0))时内存增长.这样做的好主意?
根据我的观察,这是正在发生的事情。确实不存在内存泄漏。相反,Python 的内存管理代码(可能与您所在的任何操作系统的内存管理有关)决定保留程序中原始字典(没有连接数组的字典)使用的空间。但是,它可以免费重复使用。我通过执行以下操作证明了这一点:
当我这样做时,我发现使用的内存量仅从 ~900 GB 增加到 ~1.3 GB。如果没有额外的字典内存,根据我的计算,Numpy 数据本身应该占用大约 427 MB,所以这个数字加起来。我们的函数创建的第二个初始的、未连接的字典只是使用了已经分配的内存。
如果您确实无法使用超过 600 MB 的内存,那么我建议您使用 Numpy 数组,有点类似于 Python 列表内部所做的操作:分配具有一定列数的数组,以及当您使用这些列时向上,创建一个包含更多列的放大数组并将数据复制过来。这将减少串联的数量,这意味着它会更快(尽管仍然不如列表快),同时保持较低的内存使用量。当然,实施起来也比较痛苦。
|   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           11534 次  |  
        
|   最近记录:  |