#python #numpy #hdf5 #pytables
#python #numpy #hdf5 #pytables
Вопрос:
У меня есть довольно большой файл HDF5, созданный PyTables, который я пытаюсь прочитать в кластере. Я столкнулся с проблемой с NumPy, когда читал в отдельном фрагменте. Давайте рассмотрим пример:
Общая форма массива в файле HDF5 равна,
In [13]: data.shape
Out[13]: (21933063, 800, 3)
Каждая запись в этом массиве является np.float64
.
Я заставляю каждый узел считывать фрагменты размера (21933063,10,3)
. К сожалению, NumPy, похоже, не может прочитать все 21 миллион вложенных разделов одновременно. Я попытался сделать это последовательно, разделив эти фрагменты на 10 фрагментов размера (2193306,10,3)
, а затем используя следующее сокращение, чтобы все заработало:
In [8]: a = reduce(lambda x,y : np.append(x,y,axis=0), [np.array(data[i*
chunksize: (i 1)*chunksize,:10],dtype=np.float64) for i in xrange(k)])
In [9]:
где 1 <= k <= 10
и chunksize = 2193306
. Этот код работает для k <= 9
; в противном случае я получаю следующее:
In [8]: a = reduce(lambda x,y : np.append(x,y,axis=0), [np.array(data[i*
chunksize: (i 1)*chunksize,:10],dtype=np.float64) for i in xrange(k)])
Floating point exception
home@mybox 00:00:00 ~
$
Я попытался использовать memcheck
инструмент Valgrind, чтобы выяснить, что происходит, и кажется, что PyTables является виновником. Два основных файла, которые отображаются в трассировке, — это libhdf5.so.6
и файл, связанный с blosc
.
Кроме того, обратите внимание, что если у меня есть k=8
, я получаю:
In [12]: a.shape
Out[12]: (17546448, 10, 3)
Но если я добавлю последний подраздел, я получу:
In [14]: a = np.append(a,np.array(data[8*chunksize:9*chunksize,:10],
dtype=np.float64))
In [15]: a.shape
Out[15]: (592192620,)
У кого-нибудь есть идеи, что делать? Спасибо!
Комментарии:
1. Какую ошибку вы получаете при непосредственном считывании данных в массив numpy? Я бы посоветовал вам предварительно выделить целевой массив вместо того, чтобы пытаться создать его путем добавления нескольких массивов.
Ответ №1:
Вы пытались выделить такой большой массив раньше (как предлагает DaveP)?
In [16]: N.empty((21000000,800,3))
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
...
ValueError: array is too big.
Это на 32-битном Python.
На самом деле вам понадобится 20e6*800*3*8/ 1e9=384 Гбайт памяти!
Для одного Float64 требуется 8 байт.
Вам действительно нужен весь массив сразу?
Извините, не прочитал сообщение должным образом.
Ваш массив с k = 8 подразделами уже имеет размер около 4,1 Гбайт. Может быть, в этом проблема?
Работает ли это, если вы используете только 8 вместо 10 для последнего измерения?
Еще одно предложение, я бы попробовал сначала изменить размер массива, а затем заполнить его:
a = zeros((4,8,3))
a = resize(a, (8,8,3))
a[4:] = ones((4,8,3))