Использование ОЗУ при работе с массивами numpy и списками Python - PullRequest
0 голосов
/ 19 июня 2020

У меня проблемы с памятью, и я не понимаю, почему. Я использую Google Colab, что дает мне 12 ГБ ОЗУ и позволяет мне посмотреть, как используется ОЗУ.

Я читаю np.array из файлов и загружаю каждый массив в список.

database_list = list()
for filename in glob.glob('*.npy'):
  temp_img = np.load(filename)
  temp_img = temp_img.reshape((-1, 64)).astype('float32')
  temp_img = cv2.resize(temp_img, (64, 3072), interpolation=cv2.INTER_LINEAR)
  database_list.append(temp_img)

Код print("INTER_LINEAR: %d bytes" % (sys.getsizeof(database_list))) печатает:

INTER_LINEAR : 124920 байт

Это то же значение для массивов, преобразованных в 64x64, 512x64, 1024x64, 2048x64 и 3072x64. Но если я изменю эти массивы как 4096x64, я получаю сообщение об ошибке, так как используется слишком много ОЗУ.

С массивами 3072x64 я вижу, что использование ОЗУ становится все выше и выше, а затем уменьшается.

Моя конечная цель - обнулить каждый массив до размера 8192x64, но мой сеанс cra sh раньше; но это другая проблема.

Как используется оперативная память? Почему, если массивы имеют разные размеры, список имеет одинаковый размер? Как python загружает и управляет этим файлом, что объясняет историю использования ОЗУ?

EDIT:

Затем

sizeofelem = database_list[0].nbytes 
#all arrays have now the same dimensions MxN, so despite its content, they should occupy the same memory
total_size = sizeofelem * len(database_list)

работает, а total_size отражает правильный размер списка?

1 Ответ

0 голосов
/ 01 июля 2020

У меня есть решение.

Прежде всего, как указал Дэн Машек , я измеряю память, используемую массивом, который представляет собой набор указателей ( примерно сказано). Чтобы измерить реальное использование памяти:

(database_list[0].nbytes * len(database_list) / 1000000, "MB")

, где database_list[0].nbytes является надежным, поскольку все элементы в database_list имеют одинаковый размер. Чтобы быть более точным, я должен добавить метаданные массива и, в конечном итоге, все данные, связанные с ним (если, например, я храню в массиве другие структуры).

Чтобы иметь меньшее влияние на память, я должен знать тип данных, которые я читаю, то есть значения в диапазоне 0-65535, поэтому:

database_list = list()
for filename in glob.glob('*.npy'):
  temp_img = np.load(filename)
  temp_img = temp_img.reshape((-1, 64)).astype(np.uint16)
  database_list.append(temp_img)

Более того, если я выполняю некоторые вычисления с данными, хранящимися в database_list, например, нормализация значения в диапазоне от 0 до 1, например database_list = database_list/ 65535.0 (NB: список_базы_данных, как список, не поддерживает эту операцию), я должен выполнить другое приведение, потому что Python приводит тип к чему-то вроде float64.

...