Как объединить очень большие массивы numpy? - PullRequest
0 голосов
/ 07 июня 2018

У меня будет много Numpy массивов , хранящихся в npz файлах, которые сохраняются с использованием функции savez_compressed .

Я делю информацию на множество массивов, потому что, если нет, то функции, которые я использую, аварийно завершают работу из-за проблем с памятью.Данные не редки.

Мне нужно будет объединить всю эту информацию в одном уникальном массиве (чтобы иметь возможность обрабатывать ее с помощью некоторых подпрограмм) и сохранить ее на диске (чтобы обрабатывать ее много раз с параметрами diffente)).

Массивы не помещаются в ОЗУ + подкачка памяти.

Как объединить их в уникальный массив и сохранить на диск?

Я подозреваю, что мне следует использовать mmap_mode , но я не понимаю, как именно.Кроме того, я думаю, что это может быть связано с некоторыми проблемами с производительностью, если я сначала не зарезервировал непрерывное дисковое пространство.

Я прочитал эту публикацию, но я все еще не могу понять, как это сделать.


РЕДАКТИРОВАТЬ

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

Это из-за следующего: Массивы содержат информацию (из физических симуляций) упорядоченного времени.Среди аргументов функций пользователь может установить начальный и последний раз для обработки.Кроме того, он / она может установить размер фрагмента обработки (что важно, поскольку это влияет на производительность, но допустимый размер фрагмента зависит от вычислительных ресурсов).Из-за этого я не могу хранить данные как отдельные фрагменты.

Способ построения этого конкретного массива (тот, который я пытаюсь создать) не важен, пока он работает.

Ответы [ 2 ]

0 голосов
/ 08 июня 2018

Вы должны иметь возможность загружать чанк по чанку в массиве np.memap:

import numpy as np

data_files = ['file1.npz', 'file2.npz2', ...]

# If you do not know the final size beforehand you need to
# go through the chunks once first to check their sizes
rows = 0
cols = None
dtype = None
for data_file in data_files:
    with np.load(data_file) as data:
        chunk = data['array']
        rows += chunk.shape[0]
        cols = chunk.shape[1]
        dtype = chunk.dtype

# Once the size is know create memmap and write chunks
merged = np.memmap('merged.buffer', dtype=dtype, mode='w+', shape=(rows, cols))
idx = 0
for data_file in data_files:
    with np.load(data_file) as data:
        chunk = data['array']
        merged[idx:idx + len(chunk)] = chunk
        idx += len(chunk)

Однако, как указано в комментариях, работа с измерением, которое не является самым быстрым, будет очень медленным.

0 голосов
/ 08 июня 2018

Это пример того, как записать 90 ГБ легко сжимаемых данных на диск.Здесь упоминаются наиболее важные моменты https://stackoverflow.com/a/48405220/4045774

Скорость записи / чтения должна быть в диапазоне (300 МБ / с, 500 МБ / с) на обычном жестком диске.

Пример

import numpy as np
import tables #register blosc
import h5py as h5
import h5py_cache as h5c
import time

def read_the_arrays():
  #Easily compressable data
  #A lot smaller than your actual array, I do not have that much RAM
  return np.arange(10*int(15E3)).reshape(10,int(15E3))

def writing(hdf5_path):
  # As we are writing whole chunks here this isn't realy needed,
  # if you forget to set a large enough chunk-cache-size when not writing or reading 
  # whole chunks, the performance will be extremely bad. (chunks can only be read or written as a whole)
  f = h5c.File(hdf5_path, 'w',chunk_cache_mem_size=1024**2*1000) #1000 MB cache size
  dset = f.create_dataset("your_data", shape=(int(15E5),int(15E3)),dtype=np.float32,chunks=(10000,100),compression=32001,compression_opts=(0, 0, 0, 0, 9, 1, 1), shuffle=False)

  #Lets write to the dataset
  for i in range(0,int(15E5),10):
    dset[i:i+10,:]=read_the_arrays()

  f.close()

def reading(hdf5_path):
  f = h5c.File(hdf5_path, 'r',chunk_cache_mem_size=1024**2*1000) #1000 MB cache size
  dset = f["your_data"]

  #Read chunks
  for i in range(0,int(15E3),10):
    data=np.copy(dset[:,i:i+10])
  f.close()

hdf5_path='Test.h5'
t1=time.time()
writing(hdf5_path)
print(time.time()-t1)
t1=time.time()
reading(hdf5_path)
print(time.time()-t1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...