переполнение памяти при использовании numpy нагрузки в цикле - PullRequest
4 голосов
/ 12 февраля 2012

Цикл загрузки файлов npz приводит к переполнению памяти (в зависимости от длины списка файлов).

Кажется, что ничего из следующего не помогает

  1. Удаление переменной, которая хранитданные в файле.

  2. Использование mmap.

  3. вызов gc.collect () (сборщик мусора).

Следующий код должен воспроизводить это явление:

import numpy as np

# generate a file for the demo
X = np.random.randn(1000,1000)
np.savez('tmp.npz',X=X)


# here come the overflow:
for i in xrange(1000000):
    data = np.load('tmp.npz')
    data.close()  # avoid the "too many files are open" error

в моем реальном приложении цикл проходит по списку файлов, а переполнение превышает 24 ГБ ОЗУ!обратите внимание, что это было опробовано в Ubuntu 11.10, и для numpy v 1.5.1, и для 1.6.0

Я подал отчет в numpy ticket 2048 , но это может бытьболее широкий интерес, и поэтому я публикую его здесь (более того, я не уверен, что это ошибка, но может быть результатом моего плохого программирования).

SOLUTION (by HYRY):

команде

del data.f

должна предшествовать команда

data.close()

для получения дополнительной информации и метода поиска решения, пожалуйста, прочитайте добрый ответ HYRY ниже

1 Ответ

3 голосов
/ 12 февраля 2012

Я думаю, что это ошибка, и, возможно, я нашел решение: позвоните "del data.f".

for i in xrange(10000000):
    data = np.load('tmp.npz')
    del data.f
    data.close()  # avoid the "too many files are open" error

для обнаружения утечки памяти такого типа.Вы можете использовать следующий код:

import numpy as np
import gc
# here come the overflow:
for i in xrange(10000):
    data = np.load('tmp.npz')
    data.close()  # avoid the "too many files are open" error

d = dict()
for o in gc.get_objects():
    name = type(o).__name__
    if name not in d:
        d[name] = 1
    else:
        d[name] += 1

items = d.items()
items.sort(key=lambda x:x[1])
for key, value in items:
    print key, value

После тестовой программы я создал объекты dict и count в gc.get_objects ().Вот вывод:

...
wrapper_descriptor 1382
function 2330
tuple 9117
BagObj 10000
NpzFile 10000
list 20288
dict 21001

Из результата мы знаем, что что-то не так с BagObj и NpzFile.Найдите код:

class NpzFile(object):
    def __init__(self, fid, own_fid=False):
        ...
        self.zip = _zip
        self.f = BagObj(self)
        if own_fid:
            self.fid = fid
        else:
            self.fid = None

    def close(self):
        """
        Close the file.

        """
        if self.zip is not None:
            self.zip.close()
            self.zip = None
        if self.fid is not None:
            self.fid.close()
            self.fid = None

    def __del__(self):
        self.close()

class BagObj(object):
    def __init__(self, obj):
        self._obj = obj
    def __getattribute__(self, key):
        try:
            return object.__getattribute__(self, '_obj')[key]
        except KeyError:
            raise AttributeError, key

NpzFile имеет del (), NpzFile.f - это BagObj, а BagObj._obj - это NpzFile, это ссылочный цикл, который вызовет и NpzFileBagObj не коллекционируется.Вот некоторые пояснения в документе Python: http://docs.python.org/library/gc.html#gc.garbage

Итак, чтобы разорвать ссылочный цикл, потребуется вызвать «del data.f»

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...