Zarządzanie pamięcią R / nie można przydzielić wektora o rozmiarze n Mb

149

Mam problemy z używaniem dużych obiektów w R. Na przykład:

> memory.limit(4000)
> a = matrix(NA, 1500000, 60)
> a = matrix(NA, 2500000, 60)
> a = matrix(NA, 3500000, 60)
Error: cannot allocate vector of size 801.1 Mb
> a = matrix(NA, 2500000, 60)
Error: cannot allocate vector of size 572.2 Mb # Can't go smaller anymore
> rm(list=ls(all=TRUE))
> a = matrix(NA, 3500000, 60) # Now it works
> b = matrix(NA, 3500000, 60)
Error: cannot allocate vector of size 801.1 Mb # But that is all there is room for

Rozumiem, że jest to związane z trudnością uzyskania ciągłych bloków pamięci ( stąd ):

Komunikaty o błędach rozpoczynające się nie mogą przydzielić wektora rozmiaru wskazują na niepowodzenie w uzyskaniu pamięci, ponieważ rozmiar przekracza limit przestrzeni adresowej dla procesu lub, co bardziej prawdopodobne, ponieważ system nie był w stanie zapewnić pamięci. Należy zauważyć, że w przypadku kompilacji 32-bitowej może być wystarczająco dużo dostępnej pamięci, ale nie wystarczająco duży ciągły blok przestrzeni adresowej, na który można by go zmapować.

Jak mogę to obejść? Moją główną trudnością jest to, że docieram do pewnego punktu w moim skrypcie, a R nie może przydzielić 200-300 Mb dla obiektu ... Tak naprawdę nie mogę wstępnie przydzielić bloku, ponieważ potrzebuję pamięci do innego przetwarzania. Dzieje się tak nawet wtedy, gdy skrupulatnie usuwam niepotrzebne przedmioty.

EDYCJA: Tak, przepraszam: Windows XP SP3, 4 Gb RAM, R 2.12.0:

> sessionInfo()
R version 2.12.0 (2010-10-15)
Platform: i386-pc-mingw32/i386 (32-bit)

locale:
[1] LC_COLLATE=English_Caribbean.1252  LC_CTYPE=English_Caribbean.1252   
[3] LC_MONETARY=English_Caribbean.1252 LC_NUMERIC=C                      
[5] LC_TIME=English_Caribbean.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base
Benzoes
źródło
Spróbuj użyć „free”, aby zwolnić pamięć innego procesu, który nie jest używany.
Manoel Galdino
5
@ Manoel Galdino: Co to jest „darmowe”? Funkcja R?
Benjamin
3
@Manoel: W R zadanie zwalniania pamięci jest obsługiwane przez moduł odśmiecania pamięci, a nie użytkownik. Pracując na poziomie C można ręcznie Calloci z Freepamięcią, ale podejrzewam, że to nie jest to, co robi Benjamin.
Sharpie
W bibliotece XML możesz skorzystać bezpłatnie. Z dokumentacji: „Ta ogólna funkcja jest dostępna do jawnego zwalniania pamięci związanej z danym obiektem. Jest przeznaczona do użytku na zewnętrznych obiektach wskaźników, które nie mają funkcji / procedury automatycznego finalizatora, która czyści pamięć używaną przez obiekt macierzysty ”.
Manoel Galdino

Odpowiedzi:

78

Zastanów się, czy naprawdę potrzebujesz wszystkich tych danych bezpośrednio, czy też macierz może być rzadka? Jest dobre wsparcie w R (zobacz Matrixnp. Pakiet) dla rzadkich macierzy.

Ogranicz wszystkie inne procesy i obiekty w R do minimum, gdy musisz tworzyć obiekty o tym rozmiarze. Użyj, gc()aby wyczyścić nieużywaną pamięć lub lepiej utworzyć obiekt, którego potrzebujesz, w jednej sesji .

Jeśli powyższe nie pomoże, zdobądź 64-bitową maszynę z taką ilością pamięci RAM, na jaką Cię stać, i zainstaluj 64-bitową wersję R.

Jeśli nie możesz tego zrobić, istnieje wiele usług online do zdalnego przetwarzania.

Jeśli nie możesz tego zrobić, narzędzia do mapowania pamięci, takie jak pakiet ff(lub bigmemoryjak wspomina Sascha), pomogą ci zbudować nowe rozwiązanie. Z mojego ograniczonego doświadczenia ffwynika, że ​​pakiet jest bardziej zaawansowany, ale należy przeczytać High Performance Computingtemat dotyczący widoków zadań CRAN.

mdsumner
źródło
1
zadaniem jest klasyfikacja obrazu z randomForest. Potrzebuję macierzy danych szkoleniowych (do 60 pasm) i od 20 000 do 6 000 000 wierszy, aby przesłać je do randomForest. Obecnie maksymalizuję około 150 000 wierszy, ponieważ potrzebuję ciągłego bloku do przechowywania wynikowego obiektu randomForest… Dlatego też bigmemory nie pomaga, ponieważ randomForest wymaga obiektu macierzy.
Benjamin
Co masz na myśli mówiąc „utwórz tylko potrzebny obiekt w jednej sesji”?
Benjamin
utwórz 'a' tylko raz, jeśli pomylisz się za pierwszym razem rozpocznij nową sesję
mdsumner
1
Dodam, że w przypadku programów, które zawierają duże pętle, w których wykonuje się dużo obliczeń, ale dane wyjściowe są stosunkowo małe, bardziej wydajne w pamięci może być wywołanie wewnętrznej części pętli przez Rscript (z BASH lub Python Script) , a następnie zestawiaj / agreguj wyniki w innym skrypcie. W ten sposób pamięć jest całkowicie zwalniana po każdej iteracji. Jest trochę zmarnowanych obliczeń z ponownego ładowania / ponownego obliczania zmiennych przekazanych do pętli, ale przynajmniej możesz obejść problem z pamięcią.
Benjamin
54

W przypadku użytkowników systemu Windows następujące informacje bardzo pomogły mi w zrozumieniu niektórych ograniczeń pamięci:

  • przed otwarciem R otwórz Monitor zasobów systemu Windows (Ctrl-Alt-Delete / Uruchom Menedżera zadań / karta Wydajność / kliknij dolny przycisk `` Monitor zasobów '' / karta Pamięć)
  • zobaczysz, ile pamięci RAM wykorzystaliśmy już przed otwarciem R i przez które aplikacje. W moim przypadku zużyto 1,6 GB z całości 4 GB. Więc będę mógł zdobyć tylko 2,4 GB za R, ale teraz jest gorzej ...
  • otwórz R i utwórz zestaw danych o wielkości 1,5 GB, a następnie zmniejsz jego rozmiar do 0,5 GB, Monitor zasobów pokazuje, że moja pamięć RAM jest używana w prawie 95%.
  • użyj gc()do zbierania śmieci => działa, widzę, że użycie pamięci spada do 2 GB

wprowadź opis obrazu tutaj

Dodatkowe porady, które działają na moim komputerze:

  • przygotuj funkcje, zapisz jako plik RData, zamknij R, ponownie otwórz R i załaduj funkcje pociągu. Menedżer zasobów zwykle pokazuje mniejsze użycie pamięci, co oznacza, że nawet gc () nie odzyskuje całej możliwej pamięci, a zamykanie / ponowne otwieranie języka R działa najlepiej, aby rozpocząć z maksymalną dostępną pamięcią .
  • druga sztuczka polega na załadowaniu zestawu pociągów tylko do szkolenia (nie ładuj zestawu testowego, który zazwyczaj może być o połowę mniejszy od zestawu). Faza treningowa może maksymalnie wykorzystywać pamięć (100%), więc wszystko, co jest dostępne, jest przydatne. Wszystko to należy potraktować z przymrużeniem oka, ponieważ eksperymentuję z limitami pamięci R.
Timothée HENRY
źródło
9
R samodzielnie zbiera śmieci, gc()jest tylko iluzją. Sprawdzanie Menedżera zadań to po prostu bardzo podstawowa operacja w systemie Windows. Jedyna rada, z którą mogę się zgodzić, to zapisywanie w formacie .RData
David Arenburg,
3
@DavidArenburg gc () jest iluzją? Oznaczałoby to, że powyższy obrazek pokazujący spadek wykorzystania pamięci jest iluzją. Myślę, że się mylisz, ale mogę się mylić.
Timothée HENRY
4
Nie miałem na myśli, że gc()to nie działa. Chodzi mi tylko o to, że R robi to automatycznie, więc nie musisz robić tego ręcznie. Zobacz tutaj
David Arenburg,
2
@DavidArenburg Mogę powiedzieć, że spadek wykorzystania pamięci na powyższym obrazku jest spowodowany poleceniem gc (). Nie wierzę, że dokument, który wskazałeś, jest poprawny, przynajmniej nie dla mojej konfiguracji (Windows, R wersja 3.1.0 (2014-04-10) Platforma: i386-w64-mingw32 / i386 (32-bit)).
Timothée HENRY
15
Ok, ostatni raz. gc() DZIAŁA . Po prostu nie musisz go używać, ponieważ R robi to wewnętrznie
David Arenburg
14

Najprostszym sposobem ominięcia tego ograniczenia jest przełączenie na 64-bitowy R.

David Heffernan
źródło
25
To nie jest lekarstwo w ogóle - zmieniłem, a teraz mam Error: cannot allocate vector of size ... Gbzamiast tego (ale tak, mam dużo danych).
om-nom-nom
2
Może nie jest lekarstwem, ale bardzo pomaga. Po prostu załaduj pamięć RAM i kontynuuj zwiększanie pamięci .limit (). A może pomyśl o partycjonowaniu / próbkowaniu danych.
random_forest_fanatic
Jeśli masz problemy nawet w wersji 64-bitowej, która jest zasadniczo nieograniczona, prawdopodobnie chodzi o to, że próbujesz przydzielić coś naprawdę ogromnego. Czy teoretycznie obliczyłeś, jak duży powinien być wektor? W przeciwnym razie może się zdarzyć, że Twój komputer będzie potrzebował więcej pamięci RAM, ale możesz mieć tylko tyle.
hangmanwa7id
miło jest wypróbować proste rozwiązania, takie jak to, zanim bardziej oprą się o ścianę. Dzięki.
Nova
Co więcej, nie jest to wyłącznie problem z systemem Windows. Obecnie pracuję na Ubuntu, 64-bitowym R, używam Matrix i mam trudności z manipulowaniem obiektem Matrix 20048 x 96448.
12

Napotkałem podobny problem i użyłem 2 dysków flash jako „ReadyBoost”. Dwa dyski dały dodatkowe 8 GB pamięci (dla pamięci podręcznej) i rozwiązały problem, a także zwiększyły szybkość całego systemu. Aby użyć Readyboost, kliknij prawym przyciskiem myszy dysk, przejdź do właściwości i wybierz „ReadyBoost” i wybierz przycisk opcji „użyj tego urządzenia” i kliknij zastosuj lub ok, aby skonfigurować.

Kwaku Damoah
źródło
11

Poszedłem na stronę pomocy memor.limit i dowiedziałem się, że na moim komputerze R domyślnie może używać do ~ 1,5 GB pamięci RAM i że użytkownik może zwiększyć ten limit. Używając poniższego kodu,

>memory.limit()
[1] 1535.875
> memory.limit(size=1800)

pomógł mi rozwiązać mój problem.

Rajib Kumar De
źródło
1
Dlaczego głosowanie odrzucono? Oczywiście, jest to niebezpieczne podejście, ale często może pomóc, jeśli wystarczy przydzielić trochę więcej pamięci do sesji, aby działała.
Jeppe Olsen
3
To jest tylko rozwiązanie specyficzne dla systemu Windows
Jinhua Wang
9

Jeśli uruchamiasz skrypt w środowisku linux, możesz użyć tego polecenia:

bsub -q server_name -R "rusage[mem=requested_memory]" "Rscript script_name.R"

a serwer przydzieli Ci żądaną pamięć (zgodnie z limitami serwera, ale z dobrym serwerem - można użyć wielkich plików)

nurit
źródło
1
Czy mogę tego używać na instancji Amazon EC2? Jeśli tak, co mam zastąpić server_name? Wpadam na to, cannot allocate vector size...próbując zrobić ogromną macierz terminów dokumentacyjnych na AMI i nie mogę zrozumieć, dlaczego nie ma wystarczającej ilości pamięci, ani o ile więcej muszę wypożyczyć. Dziękuję Ci!
seth127
Jestem początkującym użytkownikiem Ubuntu i używam na nim Rstudio. Mam 16 GB RAM. Jak zastosować proces przedstawiony w odpowiedzi. Dzięki
runjumpfly
3

Wspomniana powyżej metoda zapisywania / ładowania działa dla mnie. Nie jestem pewien, jak / czy gc()rozszarpuje pamięć, ale wydaje się, że działa.

# defrag memory 
save.image(file="temp.RData")
rm(list=ls())
load(file="temp.RData")
Simon Woodward
źródło