我有一个类似下面的函数,它递归地将一个大数组分成两个子数组,并收集所有子数组以备将来处理。我的问题是,是否有办法在拆分过程中产生子数组以减少内存占用,例如,split调用的数组很大,~50G
def split(array, subarrays):
n = len(array)
if n == 1:
return
else:
i = n / 2
subarray1 = array[:i]
subarrays.append(subarray1)
subarray2 = array[i:]
subarrays.append(subarray2)
split(subarray1, subarrays)
split(subarray2, subarrays)
return
subarrays = []
# In production, range(10) will be replaced with a huge array, e.g. 50G
split(range(10), subarrays)
for i in subarrays:
print i
# do some other stuff with each subarray
这实际上会增加内存占用。每次对一个列表进行切片时,除了旧列表之外,还会得到一个新列表。在
例如:
你真正想做的是把原始数据分块读入。在
你可以试着用一个memoryview,伊莱本德斯基写了一个很好的blog entry。在
不过,我会尽力总结一下。在对象上创建memoryview时,您正在创建对存储对象的内存中的(ctype)数据结构的引用。memoryview切片是在该数据结构中查找某些值的引用。无需在同一结构上复制多个基础视图即可。这就像对列表或数组进行切片一样。在
但是,您的数据必须支持缓冲区协议(numpy数组和bytearray可以做到这一点,但是列表不支持)。在
我想加上这一行就足够了
并将其传递给split而不是数组。在
不过,请注意两件事:
示例:
^{pr2}$当然,所有这些都是假设您可以在一个时间点将50GB加载到内存中。如果您不能这样做,您应该看看mmap模块。在
编辑-字符串的numpy数组
好吧,从技术上讲,它确实有效。它只是展示了numpy如何存储字符串数组。那就是:糟糕;)
如果像这样创建一个由字符串组成的numpy数组:
您可以看到dtype是
|S5
,表示长度为5的字符串。较短字符串的“missing”位置用空(零)字节(\x00
)填充(numpy通常为方便起见而隐藏这些字节)。这是因为numpy使用一个连续的2D数组将字符串存储在内存中,以允许真正快速的随机访问。在这意味着,数组中的所有条目消耗的内存与最长的字符串相同。
把这个高度构造的数组想象成一个极端的例子:
它包含一个非常长的字符串(600.000个字符,每个1个字节)和10.000个只有1个字节的字符串。所以总内存消耗应该在600KB左右。如果您创建这个数组,尽管它占用了6GB内存。在
如果你的字符串在大小上有很大的不同,你可能在这里浪费了大量的内存。也许你应该重新考虑使用numpy数组。在
我不知道你想达到什么目的。是的,您可以使用
yield
逐个返回子数组。但是它们不会按排序顺序排列,而且拆分过程仍然会使内存使用量增加一倍。但我想这比把它增加35倍要好,这是使用50G列表中的代码会发生的事情。在输出
^{pr2}$相关问题 更多 >
编程相关推荐