Dask Array + hdf5读取性能

时间:2017-09-09 19:43:06

标签: dask

我有大量的大整数数组存储在hdf5格式的文件中。我发现将这些数据表示为dask数组(而不是h5py.File对象列表)可以方便地索引数据,但是从磁盘加载数据切片非常慢。

这是一个示例,其中dsetsh5py.File个对象的列表,而x是从dask.array个对象构建的h5py.File。 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中降低加载时​​间吗?

编辑:在这里' sa repo我用jupyter笔记本制作了一些伪造的数据,将一些假数据保存到磁盘*.h5 files,然后将加载性能与原始h5py或{{ 1}}(与分块匹配)。在这些测试中,我发现在循环中使用dask加载数据的速度比h5py中的等效操作快8-10倍。

1 个答案:

答案 0 :(得分:0)

HDF5文件的读取性能不佳通常是由于文件分块的方式与dask.array的分块方式不匹配造成的。

例如,在极端情况下,如果您的HDF5文件按行分块并且您的dask.array按列读取块,则每个块读取整个文件,这很容易导致100x减速

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

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

你应该将你的from_array调用与这些块对齐

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

或者,如果这些块小于最佳值,那么您应该尝试将每个维度中的chunksize设计为整数倍

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

如果您的数据集没有分块

>>> d.chunks
None

然后,您的数据集按C顺序排列,您应该避免在后一维度中进行分块

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

您应该选择足够大的块大小来隐藏任务调度的开销。 Dask对每个块施加几百微秒的开销。如果你的块很小,那么这个开销可能占主导地位。我通常拍摄大小约为100MB的块,尽管这种情况因应用程序而异。