2014-02-13 3 views
8

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

Насколько я понял, .value метод h5py читает весь набор данных и сбрасывает его в массив, который медленно и не рекомендуются (и должны быть заменены в целом [()] правильный способ заключается в использовании Numpy-эск нарезку

Однако я получаю раздражающие результаты (с 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 копирует весь набор данных в память, в то время как нарезка только извлекает подходящую подчасти. Мне интересно, почему резка в файле slower, чем копирование всего массива, а затем резка в памяти. Я всегда думал, что hdf5/h5py был реализован специально, так что срезанные субчастицы всегда были бы самыми быстрыми.

ответ

15

Для быстрой нарезки с h5py, прилипают к "простой ванили" срез обозначения:

file['test'][0:300000] 

или, например, чтение любой другой элемент:

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

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

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

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

[1] http://docs.h5py.org/en/latest/high/dataset.html#fancy-indexing

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

+1

Файл выражения ['test'] [range (300000)] вызывает h5py версию «fancy indexing» <- Вот и все! Я не ожидал, что h5py сделает это, учитывая, что это диапазон, но это имеет смысл. И спасибо за ссылки, они полезны. – JiaYow

2

Судя по названию вашего поста, то «правильный» способ порезать наборов данных массива является использование встроенного ломтиком нотации

Все ваши ответы будут эквивалентны файла [ ​​«тест»] [:]

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

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

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

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

+0

Пожалуйста, см мое обновление – JiaYow

2

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

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

+0

Пожалуйста, см мое обновление – JiaYow

+0

Производительность нарезки в памяти по сравнению с нарезкой в ​​файле зависит от а много вещей, включая скорость вашего диска и накладные расходы файловой системы. Возможно, что удаление 300 000 транзакций несет больше накладных расходов, чем просто чтение всего массива, почти так же, как использование tar для копирования архива из 300 000 крошечных файлов ускорит процесс. –

+0

Я немного поиграл, и я получаю более высокую производительность, если я прочитал * одну строку из файла, чем если бы я загрузил весь массив. То есть 'file [" test "] [100]' быстрее, чем 'file [" test "]. Value'. Похоже, что h5py не реализован для преобразования индексации таким образом в нарезку, даже в вашем случае, когда он эквивалентен 'Slice (None)'. Теперь, когда я думаю об этом, мне пришлось вручную преобразовать индексы массива в объекты «Slice» один раз, чтобы ускорить чтение HDF5. –

Смежные вопросы