Почему gc () не освобождает память?

Я запускаю симуляции на Windows 64bit-computer с оперативной памятью 64 ГБ . Использование памяти достигает 55% , и после законченного симулятора я удаляю все объекты в рабочем пространстве с помощью rm (list = ls ()) , а затем double дс() .

Я предположил, что это освободит достаточно памяти для следующего симулятора, но на самом деле использование памяти падает всего на 1% . Консультируя множество разных форумов, я не мог найти удовлетворительного объяснения, только смутные комментарии, такие как:

«В зависимости от вашей операционной системы освобожденная память может не возвращаться в операционную систему, а храниться в пространстве процесса».

Я хотел бы найти информацию о:

  • 1) какая ОС и в каких условиях освобожденная память не возвращается ОС, а
  • 2), если есть какое-либо другое средство, кроме закрытия R, и запустить его снова для следующего запуска моделирования?
46
nl ja de
Будет ли следующий запуск исчерпан, если вы не закрываете R?
добавлено автор Bart Friederichs, источник
Вот почему вы тестируете поведение gc или rm ... в хорошем небольшом наборе данных перед выполнением всего моделирования.
добавлено автор Carl Witthoft, источник
У вас на самом деле заканчивается память?
добавлено автор Thilo, источник
Я еще не мог этого проверить. Я довольно спешу с текущим проектом, и я не хотел рисковать зацикнуться на симуляциях (им нужно от шести часов до двух дней).
добавлено автор user7417, источник

2 ответы

Сборщик мусора R несовершенен в следующем (не так) тонком способе: он перемещает объекты not (т. Е. Не имеет памяти compact ) из-за того, как он взаимодействует с библиотеками C . (Некоторые из этих других языков/реализаций страдают от этого, но другие , несмотря на то, что ему также необходимо взаимодействовать с C , у вас есть уплотнение генерации GC , из-за которого not страдает от этой проблемы).

Это означает, что если вы поочередно выделяете мелкие куски памяти, которые затем отбрасываются, а большие куски для более постоянных объектов (это обычная ситуация при обработке строк/регулярных выражений), тогда ваша память становится фрагментировано , и сборщик мусора ничего не может с этим поделать: память освобождается, но не может быть повторно использована, поскольку свободный куски слишком короткие.

Единственный способ устранить проблему - сохранить нужные объекты, перезапустить R и перезагрузить объекты.

Поскольку вы выполняете rm (list = ls ()) , т. Е. Вам не нужны какие-либо объекты, вам не нужно ничего сохранять и перезагружать, поэтому в вашем случае решение - это именно то, что вы хотите избежать - перезапустите R .

PS. Сбор мусора - весьма нетривиальная тема. Например, ruby использовал 5 (!) Разных алгоритмов GC более 20 лет . Java GC не сосать, потому что Sun/ Oracle и IBM потратили на многие человеко- лет на их соответствующих реализациях GC. С другой стороны, у R и Python есть паршивый GC - потому что никто не потрудился вкладывать необходимые человеко-годы - и они довольно популярны. Это хуже-лучше-лучше для вас.

25
добавлено
Как вы думаете, это изменится? Или нам нужно перейти на другую платформу, такую ​​как Julia или Python, или нам нужно что-то более сложное?
добавлено автор skan, источник
«Единственный способ исправить проблему - сохранить нужные объекты, перезапустить R и перезагрузить объекты». Я думаю, что это плохо говорит о Р.
добавлено автор skan, источник
@skan: R довольно хорош в том, что он делает, и крайне маловероятно, что его GC будет заменен. Python's GC тоже засасывает (это пересчет!) Я ничего не знаю о Джулии. Вообще говоря, GC имеет второстепенное значение для исследовательской платформы, такой как R. Это более важно для Python, который часто используется в производстве, но там, я думаю, могут быть изменения в карточках.
добавлено автор sds, источник
@skan: это моя точка: у R есть модель архаичной памяти.
добавлено автор sds, источник
@AlexanderHanysz: если бы это было так просто, это было бы исправлено. :-) Я не такой специалист в R, извините.
добавлено автор sds, источник
@Александр Ханиш: совсем нет. Увы, единственный способ надежно очистить память - перезапустить R. Объекты, которые пересекают выпущенную память, могут быть частью рабочей среды, которые не удаляются с помощью rm (list = ls ()) ,
добавлено автор sds, источник
Вы, кажется, противоречите себе. Нет необходимости сохранять и перезагружать, не нужно перезапускать R, не так ли?
добавлено автор Alexander Hanysz, источник
Спасибо за ответ. Это очень неинтуитивно! Можете ли вы привести примеры объектов, которые не удаляются с помощью rm (list = ls ()) ?
добавлено автор Alexander Hanysz, источник

Как вы проверяете использование памяти? Обычно виртуальная машина выделяет часть памяти, которую она использует для хранения своих данных. Некоторые из выделенных могут быть неиспользованными и помечены как бесплатные. Что GC делает, это поиск данных, которые не упоминаются нигде и маркировка соответствующих кусков памяти как неиспользуемых, это не означает, что эта память освобождается в ОС. Тем не менее с точки зрения VM теперь имеется больше свободной памяти, которая может использоваться для дальнейших вычислений.

Как выяснили другие, у вас возникли ошибки в памяти? Если нет, тогда не о чем беспокоиться.

РЕДАКТИРОВАТЬ: Это и this должно быть достаточно, чтобы понять, как распределение памяти и сборка мусора работают в R.

Из первого документа:

Иногда предпринимается попытка освободить неиспользуемые страницы   операционная система. Когда страницы освобождаются, количество свободных узлов   равный R_MaxKeepFrac раз количество выделенных узлов для каждого   класс сохраняется. Страницы, которые не нужны для выполнения этого требования,   выпущенный. Попытка освобождения страниц производится каждый R_PageReleaseFreq уровень 1   или коллекций уровня 2.

EDIT2:

Чтобы увидеть используемую память, попробуйте запустить gc() с подробным значением TRUE:

gc(verbose=T)

Вот результат с массивом из 10'000'000 целых чисел в памяти:

Garbage collection 9 = 1+0+8 (level 2) ... 
10.7 Mbytes of cons cells used (49%)
40.6 Mbytes of vectors used (72%)
          used (Mb) gc trigger (Mb) max used (Mb)
Ncells  198838 10.7     407500 21.8   350000 18.7
Vcells 5311050 40.6    7421749 56.7  5311504 40.6

И вот после отказа от ссылки на него:

Garbage collection 10 = 1+0+9 (level 2) ... 
10.7 Mbytes of cons cells used (49%)
2.4 Mbytes of vectors used (5%)
         used (Mb) gc trigger (Mb) max used (Mb)
Ncells 198821 10.7     407500 21.8   350000 18.7
Vcells 310987  2.4    5937399 45.3  5311504 40.6

Как вы можете видеть, память, используемая Vcells, упала с 40,6 МБ до 2,4 МБ.

19
добавлено
В моем компьютере (Windows 10 12GB RAM) сборщик мусора тоже работает очень плохо. Если я работаю с большими наборами данных в течение длительного времени, вся память Windows заполняется независимо от того, использую ли я gc() или нет, и компьютер становится очень медленным и непригодным для использования.
добавлено автор skan, источник
@ user7417 У меня есть обновленный ответ с дополнительной информацией.
добавлено автор Ivan Koblik, источник
@ user7417 Память, отображаемая в диспетчере задач, используемая процессом R, может быть отмечена как свободная на уровне VM, то есть все ее будут доступны для будущих вычислений. GC при выполнении сборки мусора уровня 1 или 2 может решить освободить часть системы, чтобы другие процессы использовали ее.
добавлено автор Ivan Koblik, источник
По окончании моего анализа я проверил, на самом ли деле у меня закончится память - я этого не сделал (хотя диспетчер задач Windows показал, что большая часть памяти все еще занята). Поэтому я лучше доверяю своему gc() - выводу ...
добавлено автор user7417, источник
Я проверяю использование памяти с помощью диспетчера задач Windows.
добавлено автор user7417, источник