dask数组 HDF5读取性能



我有大量存储在HDF5-Formatted文件中的大整数数组。我发现将这些数据表示为DASK数组(与h5py.File对象列表相对)很方便索引数据,但是从磁盘上加载数据切片非常慢。

这是一个示例,其中dsetsh5py.File对象的列表,而x是从这些h5py.File对象构建的dask.array。dask数组的块与h5py.File对象的块相匹配。

# Index h5py objects individually
In [68]: %%time
    ...: tmp = [d[0,0,0] for d in dsets];
    ...:
CPU times: user 23.6 ms, sys: 3.97 ms, total: 27.6 ms
Wall time: 26.8 ms
# Index dask array
In [69]: %%time
    ...: tmp = x[:,0,0,0].compute()
    ...:
CPU times: user 2.72 s, sys: 187 ms, total: 2.9 s
Wall time: 2.87 s

是什么解释了加载相同数据的时间的100倍差异?我有什么可以将负载时间降低到dask中的事情?

编辑:这是我用jupyter笔记本电脑制作的存储库,该笔记本将一些假数据保存到*.h5 files,然后将加载性能与RAW h5pydask(匹配的块)进行比较。在这些测试中,我发现在循环中使用h5py加载数据比dask中的同等操作快8-10x。

hdf5文件上的读取性能差,通常是由于文件的构成方式与dask的方式之间的不匹配。

例如,在极端情况下,如果您的HDF5文件由行和您的Dask块块。Array逐列读取,然后块读取整个文件,这很容易导致100倍放缓。

因此,您应该检查h5py.dataset对象的块

>>> d.chunks
(100, 100, 100)

,您应该对这些块来对齐您的来自_array的电话

>>> x = da.from_array(x, chunks=(100, 100, 100))

或,如果这些块小于最佳块,那么您应该尝试设计自己的块以在每个维度中成为整数倍数

>>> x = da.from_array(x, chunks=(100, 200, 300))

如果您的数据集没有块

>>> d.chunks
None

然后您的数据集以C级排列,您应该避免在后一个维度中划分

>>> x = da.from_array(x, chunks=(5, None, None))

您应该选择足够大的块尺寸以隐藏任务调度的开销。Dask施加了每块几百微秒的开销。如果您的块很小,那么这个开销可能会占主导地位。我通常的大小约为100MB,尽管这因应用而变化很大。

最新更新