numpy - 在磁盘上,保存numpy数组的最佳方法

我正在寻找一种保存大型numpy数组的快速方法,我想将它们以二进制格式保存到磁盘上,然后将它们读回内存,不幸的是,cPickle不够快。

我找到了numpy.saveznumpy.load ,例如,类似这样的事情会非常慢:


#!/usr/bin/python
import numpy as np;
import time; 
from tempfile import TemporaryFile

n = 10000000;

a = np.arange(n)
b = np.arange(n) * 10
c = np.arange(n) * -0.5

file = TemporaryFile()
np.savez(file,a = a, b = b, c = c);

file.seek(0)
t = time.time()
z = np.load(file)
print"loading time =", time.time() - t

t = time.time()
aa = z['a']
bb = z['b']
cc = z['c']
print"assining time =", time.time() - t;

更精确的是,第一行将非常快,但是将数组分配给obj的其余行非常慢:


loading time = 0.000220775604248
assining time = 2.72940087318

有没有更好的方法来保存numpy数组? 理想情况下,我希望能够在一个文件中存储多个数组。

时间:

我是hdf5的忠实拥护者,用于存储大型numpy数组,有两种在python中处理hdf5的选项:

http://www.pytables.org/

http://www.h5py.org/

它们都被设计用来有效地处理numpy数组。

savez() 将数据保存在zip文件中,压缩可能需要一些时间; 解压缩文件,你可以使用save();load()函数:


f = file("tmp.bin","wb")
np.save(f,a)
np.save(f,b)
np.save(f,c)
f.close()

f = file("tmp.bin","rb")
aa = np.load(f)
bb = np.load(f)
cc = np.load(f)
f.close()

要在一个文件中保存多个数组,只需先打开文件,然后按顺序保存或加载数组。

现在有一个基于HDF5的pickle克隆叫做hickle

https://github.com/telegraphic/hickle


import numpy as np
import hickle as hkl 

data = {'name' : 'test', 'data_arr' : [1, 2, 3, 4]}

# Dump data to file
hkl.dump(data, 'new_data_file.hkl')

# Load data from file
data2 = hkl.load('new_data_file.hkl')

print data
print data2

有效存储numpy数组的另一个方法是bloscpack :


#!/usr/bin/python
import numpy as np
import bloscpack as bp
import time

n = 10000000

a = np.arange(n)
b = np.arange(n) * 10
c = np.arange(n) * -0.5
tsizeMB = sum(i.size*i.itemsize for i in (a,b,c)) / 2**20.

blosc_args = bp.DEFAULT_BLOSC_ARGS
blosc_args['clevel'] = 6
t = time.time()
bp.pack_ndarray_file(a, 'a.blp', blosc_args=blosc_args)
bp.pack_ndarray_file(b, 'b.blp', blosc_args=blosc_args)
bp.pack_ndarray_file(c, 'c.blp', blosc_args=blosc_args)
t1 = time.time() - t
print"store time = %.2f (%.2f MB/s)" % (t1, tsizeMB / t1)

t = time.time()
a1 = bp.unpack_ndarray_file('a.blp')
b1 = bp.unpack_ndarray_file('b.blp')
c1 = bp.unpack_ndarray_file('c.blp')
t1 = time.time() - t
print"loading time = %.2f (%.2f MB/s)" % (t1, tsizeMB / t1)

我的笔记本电脑(Core2处理器,较旧的MacBook )的输出:


$ python store-blpk.py
store time = 0.19 (1216.45 MB/s)
loading time = 0.25 (898.08 MB/s)

这意味着它可以存储非常快,瓶颈通常是磁盘,


$ ll -h *.blp
-rw-r--r-- 1 faltet staff 921K Mar 6 13:50 a.blp
-rw-r--r-- 1 faltet staff 2.2M Mar 6 13:50 b.blp
-rw-r--r-- 1 faltet staff 1.4M Mar 6 13:50 c.blp

请注意,blosc压缩的使用是实现这一目标的基础,相同的脚本,但使用'clevel'=0(即禁用压缩):


$ python bench/store-blpk.py
store time = 3.36 (68.04 MB/s)
loading time = 2.61 (87.80 MB/s)

明显受到磁盘性能的影响。

要解决你可以使用joblib,可以使用joblib.dump转储需要使用的对象,


firstArray = np.arange(100)
secondArray = np.arange(50)
# I will put two arrays in dictionary and save to one file
my_dict = {'first' : firstArray, 'second' : secondArray}
joblib.dump(my_dict, 'file_name.dat')

...