为什么读取整个hdf5数据集比切片更快

mjg*_*ndo 7 python io hdf5 h5py

我想弄清楚为什么会这样:

In [1]: import time, h5py as h5
In [2]: f = h5.File('myfile.hdf5', 'r')                                                                                                                                    
In [3]: st = time.time(); data = f["data"].value[0,:,1,...]; elapsed = time.time() - st;
In [4]: elapsed
Out[4]: 11.127676010131836
In [5]: st = time.time(); data = f["data"][0,:,1,...]; elapsed2 = time.time() - st;
In [6]: elapsed2
Out[6]: 59.810582399368286
In [7]: f["data"].shape
Out[7]: (1, 4096, 6, 16, 16, 16, 16)
In [8]: f["data"].chunks
Out[8]: (1, 4096, 1, 16, 16, 16, 16)
Run Code Online (Sandbox Code Playgroud)

如您所见,将整个数据集加载到内存中然后获取切片比从数据集中获取相同切片要快.

块大小与切片匹配,因此它应该都是连续的内存,对吧?为什么那么慢呢?

使用gzip(opts=2)压缩数据集.

在Andrew的评论之后,我运行它清除两个读取之间的缓存:

elapsed1: 11.001180410385132
elapsed2: 43.19723725318909
48.61user 4.45system 0:54.65elapsed 97%CPU (0avgtext+0avgdata 8431596maxresident)k
479584inputs+0outputs (106major+3764414minor)pagefaults 0swaps
Run Code Online (Sandbox Code Playgroud)

(下一次运行在两次读取之间有10秒的延迟以清除缓存)

elapsed1: 11.46790862083435
elapsed2: 43.438515186309814

48.54user 4.66system 1:05.71elapsed 80%CPU (0avgtext+0avgdata 8431944maxresident)k
732504inputs+0outputs (220major+3764449minor)pagefaults 0swaps
Run Code Online (Sandbox Code Playgroud)

kcw*_*w78 1

首先我自己进行了测试。我没有您的 HDF5 文件,因此使用我的测试文件之一。我的测试表数据集有大约 54,000 行(看起来比你的大)。
.value[] 的计时结果给出

>>> elapsed
0.15540122985839844
Run Code Online (Sandbox Code Playgroud)

NumPy 索引的计时结果给出:

>>> elapsed2
0.12980079650878906
Run Code Online (Sandbox Code Playgroud)

因此,我认为性能上没有太大差异。也许这与我们正在测试的数据集大小或数据表的复杂性有关?

阅读一下最新的 h5py 文档有一些有趣的评论Dataset.value(从版本 2.8.0 - 2018 年 6 月 5 日;重点
是我的): Dataset.value 属性现已弃用。
该属性Dataset.value可追溯到 h5py 1.0,已被弃用,并将在以后的版本中删除。 此属性将整个数据集转储到 NumPy 数组中。.value应更新使用的代码以使用 NumPy 索引,使用mydataset[...]mydataset[()]酌情使用。

您的计时测试似乎与上面突出显示的观察结果相反。

我认为你需要请 h5py 开发人员评论性能差异(以及数据存储的位置——内存中与磁盘上)。您检查过h5py 用户组吗?

编辑: 发帖后,我发现了这个问答。它有很多好的评论,并包括 h5py 开发人员的回复:
h5py: Correct way to slice array datasets