我有大量的大整数数组存储在hdf5格式的文件中。我发现将这些数据表示为dask数组(而不是h5py.File
对象列表)可以方便地索引数据,但是从磁盘加载数据切片非常慢。
这是一个示例,其中dsets
是h5py.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倍。
答案 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的块,尽管这种情况因应用程序而异。