Почему gc () не освобождает память?
Я запускаю симуляции на 64-битном компьютере Windows с 64 ГБ оперативной памяти . Использование памяти достигает 55%, и после законченного симулятора я удаляю все объекты в рабочем пространстве с помощью rm(list=ls())
, за которым следует double gc()
.
Я предположил, что это освободит достаточно памяти для следующего симулятора, но на самом деле использование памяти падает всего на 1% . Консультируя множество разных форумов, я не мог найти удовлетворительного объяснения, только смутные комментарии, такие как:
«В зависимости от вашей операционной системы освобожденная память может не возвращаться в операционную систему, а хранится в пространстве процесса».
- Удалите пространство между полосками ggplot2
- Как сообщить интерпретатору R, как использовать прокси-сервер?
- Получение предупреждения: «« newdata »имеет 1 строку, но найденные переменные содержат 32 строки» в файле outlookа.lm
- Загружать сразу несколько пакетов
- Методы поиска близлежащих дубликатов записей
Я хотел бы найти информацию о:
- 1) какая ОС и в каких условиях освобожденная память не возвращается ОС, и
- 2) если есть какое-либо другое средство, кроме закрытия R, и начать его снова для следующего симулятора?
- Нестандартная оценка (NSE) в dplyr's filter_ и извлечение данных из MySQL
- Сделать фон графика разными цветами в разных регионах
- Создать zip-файл: команда выполнения ошибок "" имеет статус 127
- Линейный цикл регрессии для каждой независимой переменной отдельно от зависимой
- Удалите строки со всеми или некоторыми НС (отсутствующие значения) в data.frame
- Самый эффективный список методов data.frame?
- R Заseleniumные сетки долготы - широта сетки на карте
- «Правильный» способ указать необязательные аргументы в 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 – потому что никто не потрудился вкладывать необходимые человеко-годы – и они довольно популярны. Это хуже – лучше для вас.