Próbuję uruchomić jakiś dość głęboki kod rekurencyjny w R i ciągle daje mi ten błąd:
Błąd: użycie stosu C jest zbyt bliskie limitowi
Moje wyniki z CStack_info()
to:
Cstack_info()
size current direction eval_depth
67108864 8120 1 2
Mam dużo pamięci na moim komputerze, próbuję tylko dowiedzieć się, jak mogę zwiększyć CStack dla R.
EDYCJA: Ktoś poprosił o powtarzalny przykład. Oto kilka podstawowych przykładowych kodów, które powodują problem. Kilkakrotne uruchomienie f (1,1) spowoduje wyświetlenie błędu. Zauważ, że już ustawiłem --max-ppsize = 500000 i opcje (wyrażenia = 500000), więc jeśli ich nie ustawisz, możesz otrzymać błąd dotyczący jednej z tych dwóch rzeczy. Jak widać, rekurencja może tu sięgać dość głęboko i nie mam pojęcia, jak sprawić, by działała konsekwentnie. Dzięki.
f <- function(root=1,lambda=1) {
x <- c(0,1);
prob <- c(1/(lambda+1),lambda/(lambda+1));
repeat {
if(root == 0) {
break;
}
else {
child <- sample(x,2,replace=TRUE,prob);
if(child[1] == 0 && child[2] == 0) {
break;
}
if(child[1] == 1) {
child[1] <- f(root=child[1],lambda);
}
if(child[2] == 1 && child[1] == 0) {
child[2] <- f(root=child[2],lambda);
}
}
if(child[1] == 0 && child[2] == 0) {
break;
}
if(child[1] == 1 || child[2] == 1) {
root <- sample(x,1,replace=TRUE,prob);
}
}
return(root)
}
options(expressions = somethinglarge)
Odpowiedzi:
Rozmiar stosu to parametr systemu operacyjnego, regulowany dla każdego procesu (zobacz
setrlimit(2)
). Nie możesz dostosować go z poziomu R, o ile wiem, ale możesz go dostosować z powłoki przed uruchomieniem R za pomocąulimit
polecenia. Działa to tak:$ ulimit -s # print default 8192 $ R --slave -e 'Cstack_info()["size"]' size 8388608
8388608 = 1024 * 8192; R wypisuje tę samą wartość co
ulimit -s
, ale w bajtach zamiast w kilobajtach.$ ulimit -s 16384 # enlarge stack limit to 16 megs $ R --slave -e 'Cstack_info()["size"]' size 16777216
Aby na stałe zmienić to ustawienie, dodaj
ulimit
polecenie do pliku startowego powłoki, aby było wykonywane za każdym razem, gdy się logujesz. Nie mogę podać bardziej szczegółowych wskazówek, ponieważ zależy to dokładnie od posiadanej powłoki i tak dalej. Nie wiem też, jak to zrobić, aby zalogować się do środowiska graficznego (co będzie istotne, jeśli nie używasz R w oknie terminala).źródło
unlimited
.RAppArmor
Pakiet oferuje interfejssetrlimit(2)
. Ta funkcja może być wulimit
pewnym momencie dostępna w pakiecie.Podejrzewam, że niezależnie od limitu stosu, skończysz z rekurencjami, które są zbyt głębokie. Na przykład, gdy lambda = Inf, f (1) prowadzi do natychmiastowej rekursji w nieskończoność. Głębokość rekursji wydaje się być błądzeniem losowym, z pewnym prawdopodobieństwem zagłębienia się r, 1 - r zakończenia bieżącej rekursji. Zanim osiągnąłeś limit stosu, zrobiłeś wiele „głębszych” kroków. Oznacza to, że r> 1/2 i przez większość czasu będziesz po prostu kontynuować powtarzanie.
Wydaje się również, że prawie możliwe jest wyprowadzenie analitycznego lub przynajmniej numerycznego rozwiązania nawet w obliczu nieskończonej rekurencji. Można zdefiniować p jako prawdopodobieństwo, że f (1) == 1, napisać niejawne wyrażenia dla stanów „potomnych” po jednej iteracji, zrównać je z p i rozwiązać. p może być następnie użyte jako szansa powodzenia w pojedynczym losowaniu z rozkładu dwumianowego.
źródło
Ten błąd nie jest spowodowany pamięcią, ale rekursją . Funkcja wywołuje samą siebie. Aby to zilustrować, oto minimalny przykład dwóch funkcji, które wywołują się nawzajem:
change_to_factor <- function(x){ x <- change_to_character(x) as.factor(x) } change_to_character <- function(x){ x <- change_to_factor(x) as.character(x) } change_to_character("1")
Funkcje będą nadal wywoływać się nawzajem rekurencyjnie i teoretycznie nigdy się nie zakończą. Tylko kontrole w systemie zapobiegają temu w nieskończoność i zużywaniu wszystkich zasobów obliczeniowych maszyny. Musisz zmienić funkcje, aby upewnić się, że nie wywołują siebie (lub siebie nawzajem) rekurencyjnie.
źródło
Przydarzyło mi się to z zupełnie innego powodu. Przypadkowo utworzyłem bardzo długi ciąg, łącząc dwie kolumny:
output_table_subset = mutate(big_data_frame, combined_table = paste0(first_part, second_part, col = "_"))
zamiast
output_table_subset = mutate(big_data_frame, combined_table = paste0(first_part, second_part, sep = "_"))
Zajęło mi to wieczność, ponieważ nigdy nie spodziewałem się, że pasta spowodowała problem.
źródło
summarize( states = paste0(state,collapse=', ') )
. Kiedy powinienem zrobić coś takiego:summarize( states = paste0(sort(unique(state)),collapse=', ') )
. Celem było uzyskanie listy oddzielonych przecinkami unikalnych stanów dostępnych dla każdej podgrupy.Napotkałem ten sam problem z otrzymaniem błędu „Użycie stosu C jest zbyt blisko limitu” (choć dla innej aplikacji niż ta podana powyżej przez user2045093). Wypróbowałem propozycję Zwol, ale nie wyszło.
Ku mojemu zdziwieniu mogłem rozwiązać problem instalując najnowszą wersję R na OS X (obecnie: wersja 3.2.3), a także najnowszą wersję R Studio na OS X (obecnie: 0.99.840), ponieważ ja pracuję z R Studio.
Miejmy nadzieję, że to również może być pomocne.
źródło
Jednym z problemów może być to, że dzwonisz
f
do siebieplop <- function(a = 2){ pouet <- sample(a) plop(pouet) } plop() Erreur : évaluations trop profondément imbriquées : récursion infinie / options(expressions=) ? Erreur pendant l'emballage (wrapup) : évaluations trop profondément imbriquées : récursion infinie / options(expressions=) ?
źródło
Dla wszystkich informacji, nagle wpadam na to z R 3.6.1 na Windows 7 (64-bitowy). Wcześniej nie był to problem, a teraz wydaje się, że limity stosu pojawiają się wszędzie, kiedy próbuję „zapisać (.)” Dane lub nawet zrobić „save.image (.)”. To tak, jakby serializacja usuwała te stosy.
Poważnie rozważam powrót do 3.6.0. Tam się nie wydarzyło.
źródło
Mój przypadek jest być może bardziej wyjątkowy, ale może pomóc nielicznym, którzy mają dokładnie ten problem:
Mój przypadek nie ma absolutnie nic wspólnego z wykorzystaniem przestrzeni, ale R podał:
C stack usage is too close to the limit
Miałem zdefiniowaną funkcję, która jest aktualizacją funkcji podstawowej:
Ale,
przypadkowo, ta zdefiniowana funkcja została wywołana
saveRDS()
zamiastsafe_saveRDS()
.Tak więc, poza tą definicją, kiedy kod dotarł do wiersza, którego faktycznie używa
saveRDS(...)
(która wywołuje oryginalną wersję podstawową, a nie uaktualnioną), podał powyższy błąd i zgnieciony.Jeśli więc otrzymujesz ten błąd podczas wywoływania jakiejś funkcji zapisywania, sprawdź, czy przypadkowo go nie przejechałeś.
źródło
Jak napisał Martin Morgan ... Problem polega na tym, że wchodzisz zbyt głęboko w rekursję. Jeśli rekurencja w ogóle nie jest zbieżna, musisz ją przerwać samodzielnie. Mam nadzieję, że ten kod zadziała, ponieważ nie jest testowany. Jednak przynajmniej punkt powinien być tutaj jasny.
f <- function(root=1,lambda=1,depth=1) { if(depth > 256){ return(NA) } x <- c(0,1); prob <- c(1/(lambda+1),lambda/(lambda+1)); repeat { if(root == 0) { break; } else { child <- sample(x,2,replace=TRUE,prob); if(child[1] == 0 && child[2] == 0) { break; } if(child[1] == 1) { child[1] <- f(root=child[1],lambda,depth+1); } if(child[2] == 1 && child[1] == 0) { child[2] <- f(root=child[2],lambda,depth+1); } } if(child[1] == NA | child[2] == NA){ return NA; } if(child[1] == 0 && child[2] == 0) { break; } if(child[1] == 1 || child[2] == 1) { root <- sample(x,1,replace=TRUE,prob); } } return(root) }
źródło
Inny sposób spowodowania tego samego problemu:
library(debug) mtrace(lapply)
Wywołanie rekurencyjne nie jest tutaj tak oczywiste.
źródło
Jeśli używasz plot_ly, sprawdź, które kolumny przechodzisz. Wygląda na to, że dla kolumn POSIXdt / ct musisz użyć as.character () przed przejściem do plotly, inaczej otrzymasz ten wyjątek!
źródło
Często dołączam zakomentowaną
source("path/to/file/thefile.R")
linię na początku skryptu R, npthefile.R
Więc mogę łatwo skopiować i wkleić to do terminala, aby go uruchomić. Ten błąd pojawia się, jeśli zapomnę zakomentować wiersz, ponieważ uruchomienie pliku powoduje uruchomienie pliku, który uruchamia plik, który uruchamia plik, ...Jeśli to jest przyczyną, rozwiązanie jest proste: zakomentuj linię.
źródło