2017-09-09 93 views
2

我有大量的大整型數組存儲在hdf5格式的文件中。我發現將這些數據表示爲一個dask數組(而不是一個h5py.File對象列表)對索引數據非常方便,但從磁盤加載數據片非常緩慢。Dask Array + hdf5讀取性能

下面是一個例子,其中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倍時間差異?有什麼我可以做的,以減少沉重的負載時間?

編輯:這裏有一個repo我有jupyter筆記本電腦,一些假的數據保存到磁盤*.h5 files,然後用比較原始h5pydask裝載性能(與分塊匹配)製成。在這些測試中,我發現在循環中使用h5py加載數據比在dask中的等效操作快8-10倍。

回答

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)) 

或者,如果這些塊是小於是最佳,那麼你應該嘗試設計你的塊大小爲每個維度的整數倍

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

如果數據集未分塊

>>> d.chunks 
None 

那麼你的數據集被安排在C-排序,你應該避免在後者的尺寸分塊

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

你應該選擇塊大小大到足以隱藏任務調度的開銷。 Dask強加每塊數百微秒的開銷。如果你的塊很小,那麼這個開銷可以占主導地位。我通常會拍攝大小約100MB的大塊,不過這種差異會因應用程序而異。

+0

我認爲組塊會是問題,所以我明確地設置'dask'塊以匹配'hdf5'塊... 今天我做了一些更多的測試與合成數據。合成數據與我的實際數據具有相同的大小,數據類型和組塊,並且我發現使用'dask'(具有匹配的塊大小)對數據進行分片比使用'h5py'在循環中分片數據長8倍。我可以發佈我用於測試的代碼,如果你想給它一個鏡頭 - 這有點長,所以我需要編輯我原來的問題。 – dvb

+0

如果你能夠生成一個小[mcve](https://stackoverflow.com/help/mcve),那麼總是讚賞任何StackOverflow問題。 – MRocklin

+0

我編輯了我的問題,包括一個鏈接到一個github回購mcve(有一些樣板,所以我沒有複製+直接粘貼代碼到我的問題) – dvb