Fehler: Die Verwendung des C-Stacks liegt zu nahe am Grenzwert


86

Ich versuche, einen ziemlich tiefen rekursiven Code in R auszuführen, und es gibt mir immer wieder den folgenden Fehler:

Fehler: Die Verwendung des C-Stacks liegt zu nahe am Grenzwert

Meine Ausgabe von CStack_info()ist:

Cstack_info()
    size    current  direction eval_depth 
67108864       8120          1          2 

Ich habe viel Speicher auf meinem Computer. Ich versuche nur herauszufinden, wie ich den CStack für R erhöhen kann.

EDIT: Jemand hat nach einem reproduzierbaren Beispiel gefragt. Hier ist ein grundlegender Beispielcode, der das Problem verursacht. Wenn Sie f (1,1) einige Male ausführen, wird der Fehler angezeigt. Beachten Sie, dass ich bereits --max-ppsize = 500000 und Optionen (Ausdrücke = 500000) festgelegt habe. Wenn Sie diese nicht festlegen, wird möglicherweise stattdessen eine Fehlermeldung zu einem dieser beiden Dinge angezeigt. Wie Sie sehen können, kann die Rekursion hier ziemlich tief gehen, und ich habe keine Ahnung, wie ich sie konsistent zum Laufen bringen kann. Vielen Dank.

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)
}

Diese Frage schlägt vielleicht voroptions(expressions = somethinglarge)
mnel

@mnel Die Ausdrucksverschachtelungstiefe, der Zeigerschutzstapel und der C-Stapel sind drei separate (aber verwandte) Dinge.
zwol

Vielen Dank für Ihre schnelle Antwort, Zack. Ich denke, dass Ihre Antwort für ein Linux-Betriebssystem sein könnte? Ich verwende derzeit Windows 7 64-Bit. Ändert das überhaupt etwas? Nochmals vielen Dank für jede Hilfe.
user2045093

2
Das Googeln der Fehlermeldung zeigt, dass dies in der Vergangenheit normalerweise ein Fehler im Benutzercode war. Daher sollten Sie Ihr Problem wahrscheinlich auf ein einfaches reproduzierbares Beispiel reduzieren und dieses hier posten.
Martin Morgan

2
Ich bin mir nicht sicher, ob der Code überhaupt einen Fehler enthält. Dies ist einfach ein Fall von Wahrscheinlichkeiten, die theoretisch zu einer unendlichen Rekursion führen könnten. f (1,1) wirft im Grunde eine Münze. Es könnte für immer auftauchen. Für eine Bedingung, bei der der Rekursionsgrad unbekannt und unbegrenzt ist, ist es besser, sich etwas Iterativeres auszudenken, indem Sie die Ergebnisse früherer sample () auswendig lernen, um zukünftige Vorgänge zu informieren. Dann besteht das einzige Risiko, dass Ihnen der Vektorspeicher oder die Festplatte ausgeht, je nachdem, wo Sie Ihren Ergebnisstau speichern. Rekursion kann teuer und spröde sein.
Robert Casey

Antworten:


56

Die Stapelgröße ist ein pro Prozess einstellbarer Betriebssystemparameter (siehe setrlimit(2)). Sie können es nicht innerhalb von R anpassen, soweit ich das beurteilen kann, aber Sie können es über die Shell anpassen, bevor Sie R mit dem ulimitBefehl starten . Es funktioniert so:

$ ulimit -s # print default
8192
$ R --slave -e 'Cstack_info()["size"]'
   size 
8388608

8388608 = 1024 * 8192; R druckt den gleichen Wert wie ulimit -s, jedoch in Bytes anstelle von Kilobytes.

$ ulimit -s 16384 # enlarge stack limit to 16 megs
$ R --slave -e 'Cstack_info()["size"]'
    size 
16777216 

Um diese Einstellung dauerhaft anzupassen, fügen Sie den ulimitBefehl zu Ihrer Shell-Startdatei hinzu, damit er jedes Mal ausgeführt wird, wenn Sie sich anmelden. Ich kann keine genaueren Anweisungen geben, da dies genau davon abhängt, welche Shell Sie haben und was. Ich weiß auch nicht, wie ich mich in einer grafischen Umgebung anmelden soll (was relevant ist, wenn Sie R nicht in einem Terminalfenster ausführen).


12
... oder einfach einstellen unlimited.
Paul Hiemstra

1
Das RAppArmorPaket bietet eine Schnittstelle zu setrlimit(2). Diese Funktionalität wird möglicherweise ulimitirgendwann im Paket verfügbar sein.
krlmlr

2
Diese Funktion ist im RAppArmor- Paket nicht mehr vorhanden . Irgendwelche Ideen, wohin es ging?
CoderGuy123

2
Was ist das Update für Windows?
S.Perera

2
Durch Ändern des Grenzwerts wird dies nicht behoben. Eine rekursive Funktion läuft einfach weiter, bis die Obergrenze erreicht ist.
Tom Kelly

27

Ich vermute, dass Sie unabhängig von der Stapelbeschränkung zu tiefe Rekursionen erhalten. Zum Beispiel führt f (1) mit Lambda = Inf zu einer sofortigen Rekursion auf unbestimmte Zeit. Die Tiefe der Rekursion scheint ein zufälliger Spaziergang zu sein, mit einer gewissen Wahrscheinlichkeit r, tiefer zu gehen, 1 - r, die aktuelle Rekursion zu beenden. Bis Sie das Stapellimit erreicht haben, haben Sie eine große Anzahl von Schritten "tiefer" gemacht. Dies impliziert, dass r> 1/2 ist und Sie die meiste Zeit nur weiter rekursieren.

Es scheint auch fast möglich zu sein, eine analytische oder zumindest numerische Lösung abzuleiten, selbst angesichts einer unendlichen Rekursion. Man kann p als die Wahrscheinlichkeit definieren, dass f (1) == 1 ist, implizite Ausdrücke für die 'Kind'-Zustände nach einer einzelnen Iteration schreiben und diese mit p gleichsetzen und lösen. p kann dann als Erfolgschance bei einem einzelnen Draw aus einer Binomialverteilung verwendet werden.


1
Hier ist tatsächlich die richtige Antwort versteckt - stellen Sie sicher, dass Sie nicht so tief in die Abgrenzung geraten ...
Kamil S Jaron

In meinem Fall wird der Fehler durch die mehrfache Beschaffung desselben R-Skripts (dh in mehreren R-Skripten) in meinem Projekt verursacht.
Good Will

12

Dieser Fehler ist nicht auf den Speicher zurückzuführen, sondern auf die Rekursion . Eine Funktion ruft sich selbst auf. Um den Punkt zu veranschaulichen, hier ein minimales Beispiel für zwei Funktionen, die sich gegenseitig aufrufen:

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")

Fehler: Die Verwendung des C-Stacks 7971600 liegt zu nahe am Grenzwert

Die Funktionen rufen sich weiterhin rekursiv auf und werden theoretisch nie abgeschlossen. Es sind nur Überprüfungen in Ihrem System, die verhindern, dass dies auf unbestimmte Zeit auftritt und alle Rechenressourcen Ihres Computers verbraucht. Sie müssen die Funktionen ändern, um sicherzustellen, dass sie sich selbst (oder einander) nicht rekursiv aufrufen.


10

Das ist mir aus einem ganz anderen Grund passiert. Ich habe versehentlich eine superlange Zeichenfolge erstellt, während ich zwei Spalten kombiniert habe:

output_table_subset = mutate(big_data_frame,
     combined_table = paste0(first_part, second_part, col = "_"))

anstatt

output_table_subset = mutate(big_data_frame,
     combined_table = paste0(first_part, second_part, sep = "_"))

Ich habe ewig gebraucht, um es herauszufinden, da ich nie erwartet hätte, dass die Paste das Problem verursacht hat.


Das gleiche hier, aber ich habe eine Zusammenfassung gemacht. Ich hatte es so : summarize( states = paste0(state,collapse=', ') ). Wenn ich etwas hätte tun sollen wie : summarize( states = paste0(sort(unique(state)),collapse=', ') ). Ziel war es, eine durch Kommas getrennte Liste eindeutiger Zustände für jede Untergruppe zu erhalten.
Richard DiSalvo

4

Ich habe das gleiche Problem beim Empfang des Fehlers "C-Stack-Nutzung ist zu nahe am Limit" festgestellt (allerdings für eine andere Anwendung als die oben von user2045093 angegebene). Ich habe den Vorschlag von zwol ausprobiert, aber es hat nicht geklappt.

Zu meiner eigenen Überraschung konnte ich das Problem lösen, indem ich die neueste Version von R für OS X (derzeit: Version 3.2.3) sowie die neueste Version von R Studio für OS X (derzeit: 0.99.840) installierte, seit ich arbeite mit R Studio.

Hoffentlich kann Ihnen dies auch weiterhelfen.


1
Ich habe auf eine höhere Version von R umgestellt. Es hat einmal funktioniert, aber der Fehler ist erneut aufgetreten und ist jetzt konsistent. Hilfe!
murphy1310

2

Ein Problem hier kann sein, dass Sie in sich fselbst anrufen

plop <- 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=) ?

1

Zur Information aller stoße ich plötzlich mit R 3.6.1 unter Windows 7 (64-Bit) darauf. Früher war das kein Problem, und jetzt scheinen überall Stapelbeschränkungen aufzutauchen, wenn ich versuche, Daten zu "speichern (.)" Oder sogar ein "save.image (.)" Zu erstellen. Es ist, als würde die Serialisierung diese Stapel wegblasen.

Ich denke ernsthaft darüber nach, auf 3.6.0 zurückzugreifen. Ist dort nicht passiert.


1

Meins ist vielleicht ein einzigartiger Fall, kann aber den wenigen helfen, die genau dieses Problem haben:

Mein Fall hat absolut nichts mit Platznutzung zu tun, dennoch gab R Folgendes:
C stack usage is too close to the limit

Ich hatte eine definierte Funktion, die ein Upgrade der Basisfunktion darstellt:

saveRDS ()

Aus
Versehen wurde diese definierte Funktion jedoch saveRDS()anstelle von aufgerufen safe_saveRDS().
Nach dieser Definition gab der Code, wenn er in die Zeile gelangt, die tatsächlich verwendet wird saveRDS(...)(die die ursprüngliche Basisversion aufruft, nicht die aktualisierte), den obigen Fehler aus und wurde zerstört.

Wenn Sie diesen Fehler beim Aufrufen einer Speicherfunktion erhalten, prüfen Sie, ob Sie ihn nicht versehentlich überfahren haben.


0

Wie Martin Morgan schrieb ... Das Problem ist, dass Sie zu tief in die Rekursion geraten. Wenn die Rekursion überhaupt nicht konvergiert, müssen Sie sie selbst brechen. Ich hoffe, dieser Code wird funktionieren, da er nicht getestet wird. Zumindest Punkt sollte hier jedoch klar sein.

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)
}

0

Ein anderer Weg, um das gleiche Problem zu verursachen:

library(debug)
mtrace(lapply)

Der rekursive Aufruf ist hier nicht so offensichtlich.


0

Wenn Sie plot_ly verwenden, überprüfen Sie, welche Spalten Sie übergeben. Es scheint, dass Sie für POSIXdt / ct-Spalten as.character () verwenden müssen, bevor Sie an plotly übergeben, sonst erhalten Sie diese Ausnahme!


0

Ich füge häufig eine auskommentierte source("path/to/file/thefile.R")Zeile oben in ein R-Skript ein, z. B. thefile.Rdamit ich diese einfach kopieren und in das Terminal einfügen kann, um es auszuführen. Ich erhalte diese Fehlermeldung, wenn ich vergesse, die Zeile zu kommentieren, da beim Ausführen der Datei die Datei ausgeführt wird, bei der die Datei ausgeführt wird, bei der die Datei ausgeführt wird, ...

Wenn dies die Ursache ist, ist die Lösung einfach: Kommentieren Sie die Zeile aus.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.