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

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

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

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

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

  • 1) какая ОС и в каких условиях освобожденная память не возвращается ОС, и
  • 2) если есть какое-либо другое средство, кроме закрытия R, и начать его снова для следующего симулятора?

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

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

EDIT: Этого и этого должно быть достаточно, чтобы понять, как распределение памяти и assembly мусора работают в R.

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

Иногда предпринимается попытка освободить неиспользуемые страницы обратно в операционную систему. Когда страницы освобождаются, количество свободных узлов, равное R_MaxKeepFrac раз, количество выделенных узлов для каждого classа сохраняется. Выпускаются страницы, не необходимые для выполнения этого требования. Попытка выпустить страницы производится каждый набор 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 МБ.

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

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

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

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

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

  • Изменение порядка строк в матрице / области данных
  • Замените отсутствующие значения (NA) на самые последние не-NA по группам
  • Программно создавая таблицы Markdown в R с KnitR
  • Как слить 2 вектора чередующихся индексов?
  • Географическое / геопространственное расстояние между 2 списками точек lat / lon (координаты)
  • Генерирование всех различных перестановок списка в R
  • Сплит скрипка с ggplot2
  • Ошибка в if / while (условие) {: отсутствует Значение, в котором требуется TRUE / FALSE
  • Прочтите файл Stata 13 в R
  • Создание имен групп для последовательных значений
  • Как преобразовать целочисленное число в двоичный вектор?
  • Interesting Posts

    Спящий режим, настраивающий несколько источников данных и несколько сессионных заводов

    Никаких тестов с тест-бегуном «JUnit 4»

    Как я могу поместить HTML-код в Outlook 2010?

    Эффекты таймаута jQuery

    Если все методы являются статическими, если их class не имеет переменных-членов

    предупреждение: функция становится опасной

    Как вертикально разделить широкоэкранный экран на два виртуальных рабочих пространства на Ubuntu / Gnome?

    Как указать страницу ошибки по умолчанию в web.xml?

    Почему вычитание «0» в C приводит к числу, которое представляет символ?

    Перенаправление URL-адреса в расширение хром

    Почему Microsoft Edge открывает некоторые локальные веб-сайты, но не другие, где доменное имя маршрутизируется до 127.0.0.1 в файле hosts

    Как вы избегаете апострофа в одиночной кавычки в bash?

    Android: EditText теряет контент при прокрутке в ListView?

    Удобный способ планирования заданий в Mac OS X

    Как остановить непреодолимую службу Windows 7?

    Давайте будем гением компьютера.