утечка памяти с rpy

У меня есть небольшая часть в моем коде, похожая на эту (конечно, с реальными матрицами вместо заполненных нулями):

x = [rinterface.FloatSexpVector([0]*(1000**2)) for i in xrange(20)]
y = robjects.r('list')(x)

и похоже, что это вызывает утечку памяти.

При запуске следующего кода:

for i in xrange(10):
    x = [rinterface.FloatSexpVector([0]*(1000**2)) for i in xrange(20)]
    y = robjects.r('list')(x)
    del x
    del y
    robjects.r('gc(verbose=TRUE)')

Я получил:

Error: cannot allocate vector of size 7.6 Mb
In addition: Warning messages:
1: Reached total allocation of 2047Mb: see help(memory.size)
2: Reached total allocation of 2047Mb: see help(memory.size)
3: Reached total allocation of 2047Mb: see help(memory.size)
4: Reached total allocation of 2047Mb: see help(memory.size)

Это ошибка или есть что-то еще, что я должен сделать? Я также пытался создать переменную с именем, поместив их в robjects.globalenv, а затем rm() - перед gc(), но это, похоже, не работает.

Я должен упомянуть, что я запускаю rpy 2.3dev в Windows, но это происходит и в Linux с rpy 2.2.6 (хотя, поскольку Linux работает с 64-битными версиями, а не с 32-битными, как на машине с Windows, память просто увеличивается, и я не получить ошибку 2047mb)

EDIT: кажется, что добавление gc.collect() до того, как R gc() решит проблему с первым примером кода, однако это не решило мою проблему - углубившись в мой код, я обнаружил, что строка это вызывает проблему с присвоением значения .names, аналогично этому:

x = [rinterface.FloatSexpVector([0]*(1000**2)) for i in xrange(20)]
y = robjects.r('list')(x)[0]
y.names = rinterface.StrSexpVector(['a']*len(y))

установка rinterface.NULL перед очисткой тоже не помогает. какие-либо предложения?


person itai    schedule 05.09.2012    source источник
comment
Я пропустил часть о Windows при ответе. Две вещи: 1) Windows на самом деле не поддерживается (поэтому давайте пока остановимся на Linux), 2) демонстрация Windows заставит нас задуматься, почему мы не завалены вашими вкладами для rpy2 для Windows.   -  person lgautier    schedule 05.09.2012
comment
Ну, в основном текущий порт Windows достаточно хорош. На самом деле я начал работать над этим, но затем кто-то уже выпустил более новую версию, которая просто работает для меня ... возможно, я снова вернусь к ней, когда столкнусь со следующей проблемой, связанной с Windows, с которой я столкнусь.   -  person itai    schedule 06.09.2012


Ответы (2)


Это может быть связано с тем, что Python не знает об объеме памяти, выделенной встроенным R, и, следовательно, не знает, что мусор должен быть собран.

В документации по rpy2 есть информация об использовании памяти . и более ранний вопрос по SO

Ваше редактирование предполагает, что может что-то происходить. Лучше всего подать отчет об ошибке на странице bitbucket для rpy2 и продолжить устранение неполадок там, а не здесь.

person lgautier    schedule 05.09.2012
comment
Спасибо, это помогло. Но я исследовал проблему дальше - и я понял, что есть еще одна проблема.. см. мое редактирование.. - person itai; 05.09.2012

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

попробуйте эти примеры в оболочке python:

l = range(32 * 1024 * 1024)

Поэтому мы пытаемся заставить интерпретатор выделить 128 МБ непрерывной области памяти. Это будет работать (на моей машине это занимает ~ 7 секунд)

Вы можете играть с различными значениями (все еще работает для 256 МБ); попробуйте также для N = 128 * 1024 * 1024; от этого значения моя машина просто зависает. Если бы я был достаточно терпелив, я бы, вероятно, вернул свою машину через несколько минут. Но дело в том, что интерпретатор не может легко выделить большие куски непрерывной области памяти.

Стоит сказать, что я могу выделить 1 ГБ памяти в C++ таким же образом, и это занимает менее 1 секунды на той же машине (i7 с 8 ГБ ОЗУ, Windows 8 или CentOS6 — я пробовал обе ОС). То же самое я пробовал с Java.

Я не тратил время на изучение того, почему распределитель кучи Python ведет себя так. Я могу только предположить, что ребята из rpy пытались отговорить/ограничить вас от выделения слишком много, поэтому они поставили более низкий лимит, чтобы ничего плохого не случилось; на самом деле у вас может быть несколько меньших массивов с некоторыми ссылочными объектами в нем (которые занимают более 4 байтов).

person Paul Ianas    schedule 05.09.2014