h5py: правильный способ нарезать наборы данных массива

Я немного запутался здесь:

Насколько я понял, h5py's .value Метод читает весь набор данных и выгружает его в массив, что является медленным и не рекомендуется (и обычно должно быть заменено [()], Правильный способ состоит в том, чтобы использовать нарезку по буквам.

Тем не менее, я получаю раздражающие результаты (с h5py 2.2.1):

import h5py
import numpy as np
>>> file = h5py.File("test.hdf5",'w')
# Just fill a test file with a numpy array test dataset
>>> file["test"] = np.arange(0,300000)

# This is TERRIBLY slow?!
>>> file["test"][range(0,300000)]
array([     0,      1,      2, ..., 299997, 299998, 299999])
# This is fast
>>> file["test"].value[range(0,300000)]
array([     0,      1,      2, ..., 299997, 299998, 299999])
# This is also fast
>>> file["test"].value[np.arange(0,300000)]
array([     0,      1,      2, ..., 299997, 299998, 299999])
# This crashes
>>> file["test"][np.arange(0,300000)]

Я думаю, что мой набор данных настолько мал, что .value не сильно снижает производительность, но как первый вариант может быть таким медленным? Какая версия здесь предпочтительнее?

Спасибо!

ОБНОВЛЕНИЕ Кажется, я не достаточно ясно, извините. Я знаю что .value копирует весь набор данных в память, в то время как нарезка извлекает только соответствующую часть. Что мне интересно, так это то, почему нарезка в файле медленнее, чем копирование всего массива, а затем нарезка в памяти. Я всегда думал, что hdf5/h5py был реализован специально, чтобы нарезка частей всегда была самой быстрой.

3 ответа

Решение

Для быстрой нарезки с помощью h5py придерживайтесь обозначения "plain-vanilla":

file['test'][0:300000]

или, например, чтение каждого другого элемента:

file['test'][0:300000:2]

Простое срезание (объекты срезов и индексы с одним целым числом) должно быть очень быстрым, поскольку оно напрямую приводит к выделению гиперслова HDF5.

Выражение file['test'][range(300000)] вызывает h5py-версию "необычного индексирования", а именно индексации через явный список индексов. В HDF5 нет собственного способа сделать это, поэтому h5py реализует (более медленный) метод в Python, который, к сожалению, имеет ужасную производительность, когда списки> 1000 элементов. Аналогично для file['test'][np.arange(300000)], что интерпретируется аналогично.

Смотрите также:

[1] http://docs.h5py.org/en/latest/high/dataset.html

[2] https://github.com/h5py/h5py/issues/293

.value Метод копирует данные в память в виде массива. Попробуйте сравнить type(file["test"]) с type(file["test"].value): первый должен быть набором данных HDF5, второй - массивом numpy.

Я недостаточно знаком с внутренними компонентами h5py или HDF5, чтобы точно сказать, почему некоторые операции с наборами данных выполняются медленно; но причина, по которой эти два элемента различны, заключается в том, что в одном случае вы вырезаете пустой массив в памяти, а в другом - набор данных HDF5 с диска.

Основываясь на заголовке вашего поста, "правильный" способ нарезать наборы данных массива - это использовать встроенную нотацию срезов.

Все ваши ответы будут эквивалентны file ["test"] [:]

[:] выбирает все элементы в массиве

Более подробную информацию о нарезке нотации можно найти здесь, http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html

Я часто использую hdf5 + python, мне никогда не приходилось использовать методы.value. Когда вы обращаетесь к набору данных в массиве, таком как myarr = file ["test"]

python копирует набор данных из hdf5 в массив для вас.

Другие вопросы по тегам