如何拆分大数据并在以后重新加入

时间:2018-12-12 22:30:28

标签: python python-3.x numpy file-io split

我的代码生成了一个大小为(1、1,n,n,m,m)的numpy数组的列表,其中n的大小可能在50-100之间,m的范围在5-10之间,具体取决于当前的情况。列表本身的长度可能多达10,000,并在代码末尾使用 pickle 进行写入/转储。对于这些数字较高的情况,或文件大小超过5-6 GB时,出现内存不足错误。下面是这种情况的虚构示例,

import numpy as np
list, list_length = [], 1000
n = 100
m = 3
for i in range(0, list_length):
   list.append(np.random.random((1, 1, n, n, m, m)))

file_path = 'C:/Users/Desktop/Temp/'
with open(file_path, 'wb') as file:
    pickle.dump(list, file)

我正在寻找一种可以帮助我的方法

  • 拆分数据,以便消除内存错误,并且
  • 以后需要时以原始格式重新加入数据

我所能想到的是:

for i in range(0, list_length):
   data = np.random.random((1, 1, n, n, m, m))
   file_path = 'C:/Users/Desktop/Temp/'+str(i)
   with open(file_path, 'wb') as file:
      pickle.dump(data, file)

,然后使用:

combined_list = []
for i in range(0, list_length):
    file_path = 'C:/Users/Desktop/Temp/single' + str(i)
    with open(file_path, 'rb') as file:
        data = pickle.load(file)
    combined_list.append(data)

使用这种方法,由于多个文件,文件大小肯定会减小,但是由于多个文件I / O操作,这也会增加处理时间。

是否有更优雅,更好的方法来做到这一点?

2 个答案:

答案 0 :(得分:0)

不要使用pickle来存储大数据,这不是序列化任何内容的有效方法。而是通过numpy.savez_compressednumpy.load函数使用内置的numpy序列化格式/函数。

系统内存不是无限的,因此在某些时候您仍然需要拆分文件(或使用更重的解决方案,例如h5py软件包提供的解决方案)。但是,如果您能够将原始列表放入内存中,那么savez_compressedload应该可以满足您的需求。

答案 1 :(得分:0)

使用@ {tel},使用savezsavez_compressed或什至是h5py之类的东西也很有用,但是尝试“重塑”缓存机制需要花费额外的精力。如果适用,有两种更简单的方法可以处理大于内存的ndarray

  • 最简单的方法当然是在Windows上启用pagefile(或其他名称),在Linux上启用swap(不确定OS X计数器部分) 。这实际上创建了足够大的内存,因此您根本不必担心内存。它将相应地保存到磁盘/从磁盘加载

  • 如果由于没有管理员权限等原因第一种方法不适用,则numpy提供另一种方法:np.memmap。此函数将ndarray映射到磁盘,以便您可以像在内存中一样对其进行索引。从技术上讲,IO是直接在硬盘上完成的,但操作系统会相应地进行缓存

第二种方法,您可以使用以下方法创建硬盘端ndarray

np.memmap('yourFileName', 'float32', 'w+', 0, 2**32)

这将立即创建一个16GB的float32数组(包含4G号码)。然后,您可以对其进行IO。许多函数都有一个out参数。您可以相应地设置out参数,以使输出不会从内存“复制”到磁盘上。

如果要使用第二种方法保存ndarray的列表,请创建很多memmap,或将它们合并到单个数组中