目前我正在处理一个非常巨大的数据集,它几乎无法适应我的内存,所以我使用了np.memmap
。但是在某些时候,我需要将数据集分为训练和测试两部分。
我发现当我想要使用一些索引数组切片np.memmap
时会出现以下情况:
(下面是代码和内存分配)
Line # Mem usage Increment Line Contents
================================================
7 29.340 MB 0.000 MB def my_func2():
8 29.340 MB 0.000 MB ARR_SIZE = (1221508/4,430)
9 29.379 MB 0.039 MB big_mmap = np.memmap('big_mem_test.mmap',shape=ARR_SIZE, dtype=np.float64, mode='r')
10 38.836 MB 9.457 MB idx = range(ARR_SIZE[0])
11 2042.605 MB 2003.770 MB sub = big_mmap[idx,:]
12 3046.766 MB 1004.160 MB sub2 = big_mmap[idx,:]
13 3046.766 MB 0.000 MB return type(sub)
但是,如果我想要连续切片,我更倾向于使用以下代码:
Line # Mem usage Increment Line Contents
================================================
15 29.336 MB 0.000 MB def my_func3():
16 29.336 MB 0.000 MB ARR_SIZE = (1221508/4,430)
17 29.375 MB 0.039 MB big_mmap = np.memmap('big_mem_test.mmap',shape=ARR_SIZE, dtype=np.float64, mode='r')
18 29.457 MB 0.082 MB sub = big_mmap[0:1221508/4,:]
19 29.457 MB 0.000 MB sub2 = big_mmap[0:1221508/4,:]
请注意,第二个例子中的18、19行没有内存分配和整个操作速度更快。
在第一个例子中,第11行有一个分配,因此整个big_mmap矩阵在切片过程中被读取。但更令人惊讶的是,第12行又有一个分配。如果执行更多类似的操作,很容易耗尽内存。
当我拆分我的数据集时,索引通常是随机的,而不是连续的,因此我无法使用big_mmap[start:end,:]符号。
我的问题是:
是否有其他方法可以允许我在不读取整个数据到内存的情况下对memmap进行切片?
为什么在用索引切片时整个矩阵都读入内存(例如一)?
为什么要重新读取和分配数据(第一个例子的第12行)?