H5Py и хранение - PullRequest
       23

H5Py и хранение

1 голос
/ 12 апреля 2020

Я пишу код, который должен сохранить очень большой массив numpy в памяти. Массив numpy настолько большой, что я не могу загрузить все это в память сразу. Но я могу рассчитать массив в кусках. Т.е. мой код выглядит примерно так:

for i in np.arange(numberOfChunks):

   myArray[(i*chunkSize):(i*(chunkSize+1)),:,:] = #... do some calculation

Поскольку я не могу загрузить myArray в память одновременно, я хочу сохранить его в файл по одному «чанку» за раз. т.е. я хочу сделать что-то вроде этого:

for i in np.arange(numberOfChunks):

   myArrayChunk = #... do some calculation to obtain chunk

   saveToFile(myArrayChunk, indicesInFile=[(i*chunkSize):(i*(chunkSize+1)),:,:], filename)

Я понимаю, что это можно сделать с помощью h5py, но я немного запутался, как это сделать. Мое текущее понимание состоит в том, что я могу сделать это:

import h5py

# Make the file
h5py_file = h5py.File(filename, "a")

# Tell it we are going to store a dataset
myArray = h5py_file.create_dataset("myArray", myArrayDimensions, compression="gzip")


for i in np.arange(numberOfChunks):

   myArrayChunk = #... do some calculation to obtain chunk

   myArray[(i*chunkSize):(i*(chunkSize+1)),:,:] = myArrayChunk

Но здесь я немного растерялся. Я читал, что если вы индексируете тип данных h5py, как я делал, когда писал myArray[(i*chunkSize):(i*(chunkSize+1)),:,:], то эта часть myArray теперь считывается в память. Так что, конечно, к концу моего oop выше, у меня все еще не осталось всего myArray в памяти? Как это спасло мою память?

Точно так же позже я хотел бы читать в моем файле по одному фрагменту за раз, делая дальнейшие вычисления. то есть я хотел бы сделать что-то вроде:

import h5py

# Read in the file
h5py_file = h5py.File(filename, "a")

# Read in myArray
myArray = h5py_file['myArray']

for i in np.arange(numberOfChunks):

   # Read in chunk
   myArrayChunk = myArray[(i*chunkSize):(i*(chunkSize+1)),:,:]

   # ... Do some calculation on myArrayChunk

Но к концу этого l oop все ли myArray теперь в памяти? Меня немного смущает, когда myArray[(i*chunkSize):(i*(chunkSize+1)),:,:] находится в памяти, а когда нет. Пожалуйста, кто-нибудь может объяснить это.

1 Ответ

1 голос
/ 13 апреля 2020

У вас есть основная идея c. Будьте осторожны, когда говорите «сохранить в память». NumPy массивы сохраняются в памяти (RAM). Данные HDF5 сохраняются на диске (не в память / ОЗУ!), А затем доступны (используемая память зависит от того, как вы обращаетесь). На первом этапе вы создаете и записываете данные порциями на диск. На втором шаге вы получаете доступ к данным с диска кусками. Рабочий пример приведен в конце.

При чтении данных с помощью h5py существует 2 способа чтения данных:
Возвращает массив NumPy:
myArrayNP = myArray[:,:,:]
Возвращает объект набора данных h5py, который работает подобно массив NumPy:
myArrayDS = myArray

Разница: объекты набора данных h5py не считываются в память все сразу. Затем вы можете нарезать их по мере необходимости. Продолжая выше, это допустимая операция для получения подмножества данных:
myArrayChunkNP = myArrayDS[i*chunkSize):(i+1)*chunkSize),:,:]

Мой пример также исправляет 1 небольшую ошибку в вашем уравнении приращения размера фрагмента. Вы имели:
myArray[(i*chunkSize):(i*(chunkSize+1)),:,:] = myArrayChunk
Вы хотите:
myArray[(i*chunkSize):(i+1)*chunkSize),:,:] = myArrayChunk

Рабочий пример (пишет и читает):

import h5py
import numpy as np

# Make the file
with h5py.File("SO_61173314.h5", "w") as h5w:

    numberOfChunks = 3
    chunkSize = 4
    print( 'WRITING %d chunks with w/ chunkSize=%d ' % (numberOfChunks,chunkSize) )
    # Write dataset to disk
    h5Array = h5w.create_dataset("myArray", (numberOfChunks*chunkSize,2,2), compression="gzip")

    for i in range(numberOfChunks):

       h5ArrayChunk = np.random.random(chunkSize*2*2).reshape(chunkSize,2,2)
       print (h5ArrayChunk)

       h5Array[(i*chunkSize):((i+1)*chunkSize),:,:] = h5ArrayChunk


with h5py.File("SO_61173314.h5", "r") as h5r:
    print( '/nREADING %d chunks with w/ chunkSize=%d/n' % (numberOfChunks,chunkSize) )

    # Access myArray dataset - Note: This is NOT a NumpPy array
    myArray = h5r['myArray']

    for i in range(numberOfChunks):

       # Read a chunk into memory (as a NumPy array)
       myArrayChunk = myArray[(i*chunkSize):((i+1)*chunkSize),:,:]

       # ... Do some calculation on myArrayChunk  
       print (myArrayChunk)
...