【发布时间】:2019-04-26 18:28:49
【问题描述】:
我正在试图弄清楚为什么会发生这种情况:
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)
如您所见,将整个数据集加载到内存中然后取出切片比从数据集中取出相同切片要快。
块大小与切片匹配,所以它应该都是连续内存,对吧?那为什么这么慢呢?
数据集使用 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
(下一次运行在两次读取之间有 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
【问题讨论】:
-
你的操作系统是什么?如果它在 Linux 上,请尝试在
/usr/bin/time /your/python/here下运行不同版本的 Python 代码。这将显示 CPU 时间花在哪里 - 内核/系统或用户空间,并提供一些关于正在发生的事情的线索。同样在 Linux 上,您可以使用strace查看两个版本中进行了哪些系统调用。我怀疑“将其全部读入内存”仅将数据解压缩一次,而较慢的方法必须多次查找和解压缩。 -
另外,如果您使用的是 LInux,请在运行每个不同版本之前flush your page cache
-
您正在使用花式切片。 stackoverflow.com/a/48405220/4045774我在“最简单的花式索引形式”中提到了这个案例。你的块也非常大。如果您使用适当的块缓存大小,则这不是必需的。
-
还有比 gzip 更快的压缩算法。如果多种语言之间的可移植性(gzip 与每个 HDF5 安装一起提供,不像更快的 blosc)不是问题,请考虑 blosc。如果您的数据提供高压缩比并存储在 HDD 上,它通常比未压缩的数据集更快。例如。来自 HDD 的 900MB/s -> stackoverflow.com/a/48997927/4045774
-
不知道
data[0][:,1]是怎么做到的。