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)]
, что интерпретируется аналогично.
Смотрите также:
.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 в массив для вас.