2017-09-09 1 views
2

Ich habe eine große Anzahl von großen Integer-Arrays in hdf5-formatierten Dateien gespeichert. Ich finde, dass das Darstellen dieser Daten als ein DASK-Array (im Gegensatz zu einer Liste von h5py.File-Objekten) zum Indexieren der Daten geeignet ist, aber das Laden von Scheiben der Daten von der Platte ist sehr langsam.Dask Array + hdf5 lesen Leistung

Hier ist ein Beispiel, wo dsets eine Liste von h5py.File Objekten und x ein dask.array aus diesen h5py.File Objekten aufgebaut ist. Das Chunking des DASK-Arrays entspricht dem Chunking der Objekte 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 

Was erklärt die 100x Unterschied in der Zeit, um die gleichen Daten zu laden? Und kann ich etwas tun, um die Ladezeit in dask zu senken?

Edit: Hier ist ein repo ich mit einem jupyter Notebook gemacht, dass einige gefälschten Daten auf dem Datenträger als *.h5 files speichert und vergleicht dann die Ladeleistung mit rohen h5py oder dask (mit angepassten Chunking). In diesen Tests finde ich, dass das Laden von Daten mit h5py in einer Schleife 8-10x schneller ist als die entsprechende Operation in dask.

Antwort

0

Schlechte Leseleistung bei HDF5-Dateien ist in der Regel auf einen Unterschied zwischen der Art und Weise, wie Ihre Datei chunked ist, und wie Ihr dask.array chunked ist, zurückzuführen.

Zum Beispiel in einer extremen Situation, wenn Ihre HDF5 Datei für Zeile und Ihre dask.array liest in Stücken durch Spalte dann jeder chunk liest die gesamte Datei gestückelt wird, die leicht in einer 100-facher Verlangsamung führen kann.

So sollten Sie die Chunking Ihrer h5py.Dataset Objekt überprüfen

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

Und Sie sollten Ihre from_array Anruf an diese Stücke

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

Oder ausrichten, wenn diese Stücke sind kleiner als optimal , dann sollten Sie versuchen, Ihre chunksize zu entwerfen ein ganzes Vielfaches in jeder Dimension

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

Wenn Ihr Datensatz wird

>>> d.chunks 
None 

Dann wird das Dataset angeordnet in C-Bestellung nicht

gestückelt und Sie sollten das vermeiden in den letzteren Dimensionen Chunking

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

Sie Brocken zu verbergen groß genug wählen sollten Größen Overhead der Aufgabenplanung. Dask verursacht einen Aufwand von einigen hundert Mikrosekunden pro Chunk. Wenn Ihre Brocken klein sind, kann dieser Overhead dominieren. Ich schieße generell auf Chunks mit einer Größe von ungefähr 100 MB, obwohl dies je nach Anwendung stark variiert.

+0

Ich dachte, Chunking wäre das Problem, also setze ich explizit die 'dask' Chunks zu den' hdf5' Chunks ... Heute habe ich noch ein paar Tests mit synthetischen Daten. Die synthetischen Daten haben die gleiche Größe, Datentyp und Chunking wie meine realen Daten, und ich finde, dass das Schneiden der Daten mit 'dask' (mit übereinstimmenden Chunk-Größen) 8x länger dauert als das Schneiden der Daten mit' h5py' in einer Schleife. Ich kann den Code, den ich zum Testen verwendet habe, posten, wenn du es ausprobieren willst - es ist ein bisschen lang, also müsste ich meine ursprüngliche Frage bearbeiten. – dvb

+0

Wenn Sie in der Lage sind, eine kleine [mcve] (https://stackoverflow.com/help/mcve) zu produzieren, dann ist das für jede StackOverflow-Frage immer eine gute Sache. – MRocklin

+0

Ich bearbeitete meine Frage, um einen Link zu einem mcve in einem Github Repo einzuschließen (es gibt ein gutes Stück Boilerplate, also kopiere ich nicht und füge den Code direkt in meine Frage ein) – dvb