16

我在这里有点困惑:

据我了解,h5py 的.value方法读取整个数据集并将其转储到一个数组中,这很慢且不鼓励(通常应替换为[()]. 正确的方法是使用 numpy-esque 切片。

但是,我得到了令人讨厌的结果(使用 h5py 2.2.1):

import h5py
import numpy as np
>>> file = h5py.File("test.hdf5",'w')
# Just fill a test file with a numpy array test dataset
>>> file["test"] = np.arange(0,300000)

# This is TERRIBLY slow?!
>>> file["test"][range(0,300000)]
array([     0,      1,      2, ..., 299997, 299998, 299999])
# This is fast
>>> file["test"].value[range(0,300000)]
array([     0,      1,      2, ..., 299997, 299998, 299999])
# This is also fast
>>> file["test"].value[np.arange(0,300000)]
array([     0,      1,      2, ..., 299997, 299998, 299999])
# This crashes
>>> file["test"][np.arange(0,300000)]

我想我的数据集很小,.value不会显着影响性能,但是第一个选项怎么会这么慢呢?这里的首选版本是什么?

谢谢!

更新 看来我不够清楚,对不起。我知道.value在切片时将整个数据集复制到内存中只检索适当的子部分。我想知道为什么在文件中切片比复制整个数组然后在内存中切片要慢。我一直认为 hdf5/h5py 是专门实现的,因此切片子部分总是最快的。

4

3 回答 3

30

要使用 h5py 进行快速切片,请使用“plain-vanilla”切片符号:

file['test'][0:300000]

或者,例如,阅读所有其他元素:

file['test'][0:300000:2]

简单切片(切片对象和单个整数索引)应该非常快,因为它直接转换为 HDF5 超切片选择。

该表达式file['test'][range(300000)]调用 h5py 的“花式索引”版本,即通过显式索引列表进行索引。在 HDF5 中没有本地方法可以做到这一点,因此 h5py 在 Python 中实现了一个(较慢的)方法,不幸的是,当列表超过 1000 个元素时,它的性能很差。同样 for file['test'][np.arange(300000)],其解释方式相同。

也可以看看:

[1] http://docs.h5py.org/en/latest/high/dataset.html#fancy-indexing

[2] https://github.com/h5py/h5py/issues/293

于 2014-02-14T22:24:57.533 回答
4

.value方法是将数据作为 numpy 数组复制到内存中。尝试比较type(file["test"])type(file["test"].value)前者应该是 HDF5 数据集,后者应该是 numpy 数组。

我对 h5py 或 HDF5 内部结构不够熟悉,无法准确告诉您某些数据集操作缓慢的原因;但是这两者不同的原因是,在一种情况下,您正在对内存中的 numpy 数组进行切片,而在另一种情况下,您正在从磁盘中切片 HDF5 数据集。

于 2014-02-14T01:42:26.527 回答
3

根据您帖子的标题,对数组数据集进行切片的“正确”方法是使用内置切片表示法

你所有的答案都相当于 file["test"][:]

[:] 选择数组中的所有元素

更多关于切片符号的信息可以在这里找到, http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html

我经常使用 hdf5 + python,我从来没有使用过 .value 方法。当您访问数组中的数据集时,例如 myarr = file["test"]

python 已经将 hdf5 中的数据集复制到一个数组中。

于 2014-02-13T22:49:17.073 回答