Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python numpy阵列的最快保存和加载选项_Python_Arrays_Performance_Numpy_Io - Fatal编程技术网

Python numpy阵列的最快保存和加载选项

Python numpy阵列的最快保存和加载选项,python,arrays,performance,numpy,io,Python,Arrays,Performance,Numpy,Io,我有一个脚本,可以生成二维numpy数组s,其中dtype=float和形状的顺序为(1e3,1e6)。现在我正在使用np.save和np.load对数组执行IO操作。但是,对于每个阵列,这些函数需要几秒钟的时间。是否有更快的方法来保存和加载整个数组(即,不必假设其内容并减少它们)?我愿意在保存之前将数组转换为另一种类型,只要数据被准确保留。对于真正大的数组,我听说过几种解决方案,它们主要是关于I/O方面的懒惰: ,将大数组映射为二进制形式 优点: 除了Numpy之外没有其他依赖项 透明替

我有一个脚本,可以生成二维
numpy
数组
s,其中
dtype=float
和形状的顺序为
(1e3,1e6)
。现在我正在使用
np.save
np.load
对数组执行IO操作。但是,对于每个阵列,这些函数需要几秒钟的时间。是否有更快的方法来保存和加载整个数组(即,不必假设其内容并减少它们)?我愿意在保存之前将
数组
转换为另一种类型,只要数据被准确保留。

对于真正大的数组,我听说过几种解决方案,它们主要是关于I/O方面的懒惰:

  • ,将大数组映射为二进制形式
    • 优点:
      • 除了Numpy之外没有其他依赖项
      • 透明替换
        ndarray
        (任何接受ndarray的类都接受
        memmap
    • 缺点:
      • 阵列的块数限制为2.5G
      • 仍然受到Numpy吞吐量的限制
  • 将Python绑定用于HDF5,这是一种bigdata就绪文件格式,如或

    • 优点:
      • 格式支持压缩、索引和其他超好的功能
      • 显然是PB级的大文件格式
    • 缺点:
      • 具有分层格式的学习曲线
      • 必须定义您的性能需求(见下文)
  • 系统(在比赛之外,提到的是Pythonicity而不是速度)

    • 优点:
      • 这是蟒蛇!(哈哈)
      • 支持各种对象
    • 缺点:
      • 可能比其他对象慢(因为瞄准的对象不是数组)

Numpy.memmap 从以下文件:

创建存储在磁盘二进制文件中的阵列的内存映射

内存映射文件用于访问磁盘上大文件的小段,而无需将整个文件读入内存

memmap对象可以在接受ndarray的任何位置使用。给定任何memmap
fp
isinstance(fp,numpy.ndarray)
返回True


HDF5阵列 从

允许您存储大量的数字数据,并可以轻松地从NumPy操作这些数据。例如,您可以将存储在磁盘上的多TB数据集进行切片,就像它们是真正的NumPy阵列一样。数千个数据集可以存储在一个文件中,可以根据需要进行分类和标记


该格式支持以各种方式压缩数据(为相同的I/O读取加载更多位),但这意味着单独查询数据变得不那么容易,但在您的情况下(纯粹加载/转储数组),它可能会更有效

这里是与PyTables的比较

由于内存限制,我无法访问
(int(1e3),int(1e6)
。 因此,我使用了更小的数组:

data = np.random.random((int(1e3), int(1e5)))
NumPy
保存

%timeit np.save('array.npy', data)
1 loops, best of 3: 4.26 s per loop
NumPy
加载

%timeit data2 = np.load('array.npy')
1 loops, best of 3: 3.43 s per loop
PyTables编写:

%%timeit
with tables.open_file('array.tbl', 'w') as h5_file:
    h5_file.create_array('/', 'data', data)

1 loops, best of 3: 4.16 s per loop
PyTables如下:

 %%timeit
 with tables.open_file('array.tbl', 'r') as h5_file:
      data2 = h5_file.root.data.read()

 1 loops, best of 3: 3.51 s per loop
这些数字非常相似,所以这里的表格没有真正的收益。 但我们已经非常接近SSD的最大写入和读取速率

写作:

Maximum write speed: 241.6 MB/s
PyTables write speed: 183.4 MB/s
阅读:

Maximum read speed: 250.2
PyTables read speed: 217.4
由于数据的随机性,压缩实际上没有帮助:

%%timeit
FILTERS = tables.Filters(complib='blosc', complevel=5)
with tables.open_file('array.tbl', mode='w', filters=FILTERS) as h5_file:
    h5_file.create_carray('/', 'data', obj=data)
1 loops, best of 3: 4.08 s per loop
压缩数据的读取速度变慢:

%%timeit
with tables.open_file('array.tbl', 'r') as h5_file:
    data2 = h5_file.root.data.read()

1 loops, best of 3: 4.01 s per loop
这与常规数据不同:

 reg_data = np.ones((int(1e3), int(1e5)))
写作速度明显加快:

%%timeit
FILTERS = tables.Filters(complib='blosc', complevel=5)
with tables.open_file('array.tbl', mode='w', filters=FILTERS) as h5_file:
    h5_file.create_carray('/', 'reg_data', obj=reg_data)
1个回路,最佳3个:每个回路849毫秒

这同样适用于阅读:

%%timeit
with tables.open_file('array.tbl', 'r') as h5_file:
    reg_data2 = h5_file.root.reg_data.read()

1 loops, best of 3: 1.7 s per loop

结论:数据越规则,使用PyTables获取数据的速度就越快。

根据我的经验,到目前为止,在硬盘和内存之间传输数据时,np.save()和np.load()是最快的解决方案。 在我意识到这个结论之前,我严重依赖于数据库和HDFS系统的数据加载。 我的测试表明: 数据库数据加载(从硬盘到内存)带宽可能约为50 MBps(字节/秒),但np.load()带宽几乎与我的硬盘最大带宽相同:2GBps(字节/秒)。两个测试环境都使用最简单的数据结构

我认为用几秒钟的时间加载一个具有形状的数组(1e3,1e6)并不是一个问题。 您的数组形状是(10001000000),其数据类型是float128,那么纯数据大小是(128/8)*1000*1000000=1600000000=16GB 如果需要4秒, 那么您的数据加载带宽是16GB/4秒=4GBps。 SATA3的最大带宽是600MBps=0.6GBps,您的数据加载带宽已经是它的6倍,您的数据加载性能几乎可以与之竞争,您还想要什么

因此,我的最终结论是:

如果可以使用np.save()和np.load(),不要使用python的Pickle,不要使用任何数据库,不要使用任何大数据系统将数据存储到硬盘中。这两个函数是迄今为止在硬盘和内存之间传输数据的最快解决方案。


我还测试了,发现它比np.load()和np.save()慢得多,所以如果您的平台中有足够的DDR内存,请使用np.save()和np.load()。

我比较了使用(我的一个项目)的几种方法。结果如下:

书写

对于大型数组,所有方法的速度都差不多。文件大小也一样,这是意料之中的,因为输入数组是随机双精度的,因此几乎不可压缩

复制绘图的代码:

导入perfplot
进口泡菜
进口numpy
进口h5py
导入表
进口南非兰特
def npy_写入(数据):
numpy.save(“npy.npy”,数据)
def hdf5_写入(数据):
f=h5py.File(“hdf5.h5”,“w”)
f、 创建数据集(“数据”,数据=数据)
def pickle_写入(数据):
以open(“test.pkl”、“wb”)作为f:
pickle.dump(数据,f)
def pytables_写入(数据):
f=表格。打开_文件(“pytables.h5”,mode=“w”)
gcolumns=f.create_组(f.root,“column