在我的程序中,我使用元素填充一个大的YYYY-MM-DD
数组,其中的元素我事先并不知道。由于每次向numpy
数组添加单个元素效率很低,因此我通过用零初始化的长度为10000的块来增加其大小。这导致最终我有一个带尾零的数组的情况。而我想要的是数组,其长度恰好是有意义元素的数量(因为后来我无法区分junky零和实际数据点的零值)。然而,直接复制切片会使RAM消耗增加一倍,这实际上是不受欢迎的,因为我的阵列非常大。我研究了numpy
函数,但它们似乎只将数组拆分成相同大小的块,这当然不适合我。
我用以下代码说明了这个问题:
numpy.split
输出:
import numpy, os, random
def check_memory(mode_peak = True, mark = ''):
"""Function for measuring the memory consumption (Linux only)"""
pid = os.getpid()
with open('/proc/{}/status'.format(pid), 'r') as ifile:
for line in ifile:
if line.startswith('VmPeak' if mode_peak else 'VmSize'):
memory = line[: -1].split(':')[1].strip().split()[0]
memory = int(memory) / (1024 * 1024)
break
mode_str = 'Peak' if mode_peak else 'Current'
print('{}{} RAM consumption: {:.3f} GB'.format(mark, mode_str, memory))
def generate_element():
"""Test element generator"""
for i in range(12345678):
yield numpy.array(random.randrange(0, 1000), dtype = 'i4')
check_memory(mode_peak = False, mark = '#1 ')
a = numpy.zeros(10000, dtype = 'i4')
i = 0
for element in generate_element():
if i == len(a):
a = numpy.concatenate((a, numpy.zeros(10000, dtype = 'i4')))
a[i] = element
i += 1
check_memory(mode_peak = False, mark = '#2 ')
a = a[: i]
check_memory(mode_peak = False, mark = '#3 ')
check_memory(mode_peak = True, mark = '#4 ')
任何人都可以帮我找到一个不会显着影响运行时或RAM消耗的解决方案吗?
修改
我尝试使用
#1 Current RAM consumption: 0.070 GB
#2 Current RAM consumption: 0.118 GB
#3 Current RAM consumption: 0.118 GB
#4 Peak RAM consumption: 0.164 GB
以及
a = numpy.delete(a, numpy.s_[i: ])
然而,它导致相同的双倍内存消耗
答案 0 :(得分:6)
numpy.split不必将数组拆分为相等大小的块。如果使用indices_or_sections
参数,则可以给出一个整数列表,它将用于拆分数组。例如:
>>> x = np.arange(8.0)
>>> np.split(x, [3, 5, 6, 10])
[array([ 0., 1., 2.]), # x[:3]
array([ 3., 4.]), # x[3:5]
array([ 5.]), # x[5:6]
array([ 6., 7.]), # x[6:10]
array([], dtype=float64)] # x[10:]
答案 1 :(得分:1)
最后我明白了。事实上,额外的内存不仅在修剪阶段消耗,而且在连接期间消耗。因此,在点#2
输出时引入峰值内存检查:
#2 Peak RAM consumption: 0.164 GB
但是,有resize()
方法,可以就地更改数组的大小/形状:
check_memory(mode_peak = False, mark = '#1 ')
page_size = 10000
a = numpy.zeros(page_size, dtype = 'i4')
i = 0
for element in generate_element():
if (i != 0) and (i % page_size == 0):
a.resize(i + page_size)
a[i] = element
i += 1
a.resize(i)
check_memory(mode_peak = False, mark = '#2 ')
check_memory(mode_peak = True, mark = '#2 ')
这导致输出:
#1 Current RAM consumption: 0.070 GB
#2 Current RAM consumption: 0.118 GB
#2 Peak RAM consumption: 0.118 GB
此外,由于没有更多的重新分配,性能也得到了显着提升。