NumPy Загрузка отдельных файлов NPY для копирования в файл MemMap приводит к высокому использованию памяти и медленной пакетной обработке - PullRequest
0 голосов
/ 16 сентября 2018

Я работаю с набором данных большого размера (Начинается с 75 ГБ -> Конечный результат двух файлов по 100 ГБ) с данными, разбитыми на около 5000 отдельных файлов Numpy .npy. Я пытаюсь просмотреть каждый файл, выполнить небольшую обработку и заполнение, а затем сохранить в одну из двух корзин. Есть несколько других массивов метаданных, но их запуск сам по себе работает нормально. Тем не менее, они должны / должны быть в состоянии выполнять обработку больших данных.

Я создаю два файла memmap в начале скрипта

f1 = np.memmap('f1.dat', dtype='float32', mode='w+', shape=(2600, 5000, 2000))
f2 = np.memmap('f2.dat', dtype='float32', mode='w+', shape=(2500, 5000, 2000))
# f1 and f2 store different sets, depending on a flag

У меня есть обработка данных, функционирующая в processData () для возврата метаданных и большого массива данных. Затем это добавляется или устанавливается для данного массива. Все это делается в перечисляемом цикле for.

for i, object in enumerate(object_list)
    meta1, meta2, data = processData(i, object)
    list_meta1.append(meta1)
    array_meta2[i] = meta2
    if flag_1:
        f1[j] = data; j+=1
    elif flag_2:
        f2[k] = data; k+=1

Я пробовал сделать это как с обработкой данных как функцией (я читал об использовании генераторов, но, вероятно, немного пропустил метку, ха-ха), так и в цикле for.

Проблема, с которой я сталкиваюсь, заключается в том, что процесс python загружается как обычно, когда я наблюдаю за ним с верхом в оболочке bash. Он «загружает» два больших файла данных в памяти VIRT до 0,199 т, а до начала загрузки файлов данных он составляет около одного или двух ГБ в RES / SHR-, что выглядит хорошо.

Однако, как только данные фактически начнут обрабатываться, как указано ниже:

data = np.load(object + ".npy")

meta1 = fetchMeta(1, object)
meta2 = fetchMeta(2, object)

if len(data) != whatItShouldBe[i]:
    sys.exit("You goof'd somewhere")
else:
    if len(data) < padding_limit:
        data = np.concatenate([np.array(data), np.zeros((padding_limit - len(data), 2000))], axis=0)

return meta1, meta2, data

Объем памяти RES быстро увеличивается, достигая около 10 ГБ при файле 400 или около того, и в определенный момент достигнет 48 ГБ из 64 ГБ системы. На протяжении всей обработки вплоть до 48 ГБ, есть несколько моментов, которые процесс Python переходит к D (который я понимаю, как непрерывный сон). Я предполагаю, что это для memmap, чтобы записать себя на диск.

Однако ручная очистка массивов не освобождает память и не ускоряет ее вообще (во всяком случае, она замедляет ее с паузами ~ 1 минута для сброса).

По сути, я знаю, что весь этот пакетный процесс может быть завершен вовремя, поскольку он просматривает первые сто или двести файлов, сохраняет их в порядке и продолжает отправлять сообщения. Тем не менее, существует эта «скрытая» проблема с памятью, которая, кажется, бросает рывок в вещах. На мой взгляд, нет никакой причины для использования памяти оставаться при высокой нагрузке (очевидно, что она будет высокой в ​​течение некоторого времени между записями на диск), но мне кажется, что отдельные блоки данных по какой-то причине хранится в памяти (после того, как они были скопированы в правую карту памяти).

Конечные примечания: Общая структура этого кода работала нормально при использовании стандартных массивов, но это был существенно меньший набор данных. Я для большей ясности анонимизировал мой код, но полную реализацию можно найти здесь: https://pastebin.com/nNZDxL0k

...