Исключение с плавающей запятой для Numpy и PyTables

#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))