Я смущен тем, как numpy's memmap
обрабатывает изменения данных при использовании копирования при записи (mmap_mode=c
).Поскольку в исходный массив на диске ничего не записано, я ожидаю, что он должен хранить все изменения в памяти и, следовательно, может исчерпать память, если вы измените каждый отдельный элемент.К моему удивлению, этого не произошло.
Я пытаюсь сократить использование памяти для своих сценариев машинного обучения, которые я запускаю в общем кластере (чем меньше памяти занимает каждый экземпляр, тем больше экземпляров я могу запуститьв то же время).У меня очень большие массивы данных (каждый> 8 Гб).Я надеюсь использовать np.memmap
для работы с этими массивами с малой памятью (доступно <4 ГБ). </p>
Однако каждый экземпляр может по-разному изменять данные (например, может каждый раз по-разному нормализовать входные данные),Это имеет значение для места для хранения.Если я использую режим r+
, то нормализация массива в моем сценарии навсегда изменит сохраненный массив.
Поскольку я не хочу избыточных копий данных, а просто хочу сохранить исходные данные вдиск, я думал, что я должен использовать режим 'c'
(копирование при записи), чтобы открыть массивы.Но тогда куда делись твои изменения?Сохраняются ли изменения только в памяти?Если это так, если я изменю весь массив, не будет ли у меня нехватка памяти в системе с малой памятью?
Вот пример теста, который я ожидал провалить:
Набольшая система памяти, создайте массив:
import numpy as np
GB = 1000**3
GiB = 1024**3
a = np.zeros((50000, 20000), dtype='float32')
bytes = a.size * a.itemsize
print('{} GB'.format(bytes / GB))
print('{} GiB'.format(bytes / GiB))
np.save('a.npy', a)
# Output:
# 4.0 GB
# 3.725290298461914 GiB
Теперь на машине с объемом памяти всего 2 ГБ происходит сбой, как и ожидалось:
a = np.load('a.npy')
Но эти два удастся, так какожидается:
a = np.load('a.npy', mmap_mode='r+')
a = np.load('a.npy', mmap_mode='c')
Проблема 1: Недостаточно памяти для запуска этого кода, пытаюсь изменить массив memmapped (не удается независимо от режима r + / c):
for i in range(a.shape[0]):
print('row {}'.format(i))
a[i,:] = i*np.arange(a.shape[1])
Почему происходит сбой (особенно, почему он не работает даже в режиме r+
, где он может записывать на диск)?Я думал, memmap
будет загружать только части массива в память?
Проблема 2: Когда я заставляю numpy сбрасывать изменения время от времени, оба r +Режим / C успешно завершить цикл. Но как режим c
может это сделать? Я не думал, что flush()
что-нибудь сделает для режима c
?Изменения не записываются на диск, поэтому они хранятся в памяти, и все же каким-то образом все изменения, которые должны превышать 3 ГБ, не вызывают ошибок нехватки памяти?
for i in range(a.shape[0]):
if i % 100 == 0:
print('row {}'.format(i))
a.flush()
a[i,:] = i*np.arange(a.shape[1])