Errore: l'utilizzo dello stack C è troppo vicino al limite


88

Sto tentando di eseguire un codice ricorsivo abbastanza profondo in R e continua a darmi questo errore:

Errore: l'utilizzo dello stack C è troppo vicino al limite

Il mio output CStack_info()è:

Cstack_info()
    size    current  direction eval_depth 
67108864       8120          1          2 

Ho molta memoria sulla mia macchina, sto solo cercando di capire come aumentare il CStack per R.

EDIT: Qualcuno ha chiesto un esempio riproducibile. Ecco un codice di esempio di base che causa il problema. Eseguendo f (1,1) alcune volte otterrai l'errore. Nota che ho già impostato --max-ppsize = 500000 e opzioni (espressioni = 500000) quindi se non li imposti potresti invece ottenere un errore su una di queste due cose. Come puoi vedere, la ricorsione può andare abbastanza in profondità qui e non ho idea di come farlo funzionare in modo coerente. Grazie.

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

1
Questa domanda suggerisce forseoptions(expressions = somethinglarge)
mnel

@mnel La profondità di annidamento delle espressioni, lo stack di protezione del puntatore e lo stack C sono tre cose separate (ma correlate).
zwol

Grazie mille per la tua pronta risposta, Zack. Penso che la tua risposta potrebbe essere per un sistema operativo Linux però? Attualmente sto eseguendo Windows 7 a 64 bit, questo cambia le cose? Grazie ancora per qualsiasi aiuto.
user2045093

2
Cercare su Google il messaggio di errore mostra che in passato si trattava di solito di un errore nel codice utente, quindi dovresti probabilmente ridurre il tuo problema a un semplice esempio riproducibile e pubblicarlo qui.
Martin Morgan

2
Non sono affatto sicuro che ci sia un errore nel codice. Questo è semplicemente un caso di probabilità che in teoria potrebbe finire con una ricorsione infinita. f (1,1) è fondamentalmente lanciare una moneta. Potrebbe continuare a venire in mente per sempre. Per una condizione in cui il livello di ricorsione è sconosciuto e illimitato, è meglio trovare qualcosa di più iterativo, utilizzando la memorizzazione dei risultati di sample () precedenti per informare le operazioni future. Quindi l'unica cosa che rischi è esaurire la memoria vettoriale, o disco, a seconda di dove stai memorizzando il tuo arretrato di risultati. La ricorsione può essere costosa e fragile.
Robert Casey

Risposte:


57

La dimensione dello stack è un parametro del sistema operativo, regolabile in base al processo (vedere setrlimit(2)). Non puoi regolarlo dall'interno di R per quanto posso dire, ma puoi regolarlo dalla shell prima di avviare R, con il ulimitcomando. Funziona così:

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

8388608 = 1024 * 8192; R stampa lo stesso valore di ulimit -s, ma in byte invece che in kilobyte.

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

Per apportare una regolazione permanente a questa impostazione, aggiungi il ulimitcomando al file di avvio della shell, in modo che venga eseguito ogni volta che accedi. Non posso fornire indicazioni più specifiche di queste, perché dipende esattamente da quale shell hai e cose del genere. Inoltre non so come farlo per l'accesso a un ambiente grafico (che sarà rilevante se non stai eseguendo R all'interno di una finestra di terminale).


12
... o semplicemente impostalo su unlimited.
Paul Hiemstra

1
Il RAppArmorpacchetto offre un'interfaccia a setrlimit(2). Questa funzionalità potrebbe diventare disponibile nel ulimitpacchetto a un certo punto.
krlmlr

2
Questa funzione non esiste più nel pacchetto RAppArmor . Qualche idea su dove sia andato?
CoderGuy123

2
Qual è la correzione per Windows?
S.Perera

2
La modifica del limite non risolverà questo problema. Una funzione ricorsiva continuerà semplicemente a essere eseguita finché non viene raggiunto il limite superiore.
Tom Kelly

27

Sospetto che, indipendentemente dal limite dello stack, ti ​​ritroverai con ricorsioni troppo profonde. Ad esempio, con lambda = Inf, f (1) porta a una ricorsione immediata, indefinitamente. La profondità della ricorsione sembra essere una passeggiata casuale, con una certa probabilità r di andare più in profondità, 1 - r di terminare la ricorsione corrente. Quando hai raggiunto il limite dello stack, hai fatto un gran numero di passaggi "più in profondità". Ciò implica che r> 1/2 e per la maggior parte del tempo continuerai semplicemente a ricorrere.

Inoltre, sembra quasi possibile derivare una soluzione analitica o quantomeno numerica anche di fronte alla ricorsione infinita. Si può definire p come la probabilità che f (1) == 1, scrivere espressioni implicite per gli stati "figli" dopo una singola iterazione, e equipararle a p, e risolvere. p può quindi essere utilizzato come possibilità di successo in una singola estrazione da una distribuzione binomiale.


1
ecco in realtà la risposta corretta nascosta - assicurati di non andare così in profondità nella recusione ...
Kamil S Jaron

Nel mio caso, l'errore è causato dall'acquisizione dello stesso script R più volte (ovvero in più script R) nel mio progetto.
Buona Volontà

15

Questo errore non è dovuto alla memoria, ma alla ricorsione . Una funzione chiama se stessa. Per illustrare il punto, ecco un esempio minimo di 2 funzioni che si chiamano a vicenda:

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

Errore: l'utilizzo dello stack C 7971600 è troppo vicino al limite

Le funzioni continueranno a chiamarsi reciprocamente in modo ricorsivo e teoricamente non verranno mai completate. Sono solo i controlli all'interno del sistema che impediscono che ciò si verifichi a tempo indeterminato e che consumi tutte le risorse di elaborazione della macchina. È necessario modificare le funzioni per assicurarsi che non chiamino se stesse (o l'una con l'altra) in modo ricorsivo.


10

Questo è successo a me per una ragione completamente diversa. Ho creato accidentalmente una stringa superlunga combinando due colonne:

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

invece di

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

Mi ci è voluto per sempre per capirlo perché non mi sarei mai aspettato che la pasta avesse causato il problema.


Lo stesso qui, ma stavo facendo un riepilogo. Ho avuto in questo modo: summarize( states = paste0(state,collapse=', ') ). Quando devo avere qualcosa di fatto come: summarize( states = paste0(sort(unique(state)),collapse=', ') ). L'obiettivo era quello di ottenere un elenco separato da virgole di stati univoci disponibili per ogni sottogruppo.
Richard DiSalvo

4

Ho riscontrato lo stesso problema di ricevere l'errore "L'utilizzo dello stack C è troppo vicino al limite" (anche se per un'altra applicazione rispetto a quella dichiarata da user2045093 sopra). Ho provato la proposta di Zwol ma non ha funzionato.

Con mia grande sorpresa, ho potuto risolvere il problema installando la versione più recente di R per OS X (attualmente: versione 3.2.3) e la versione più recente di R Studio per OS X (attualmente: 0.99.840), poiché ho sto lavorando con R Studio.

Si spera che questo possa essere di aiuto anche per te.


1
Sono passato a una versione successiva di R. Ha funzionato una volta, ma l'errore è ricomparso ed è coerente ora. Aiuto!
murphy1310

2

Un problema qui può essere che stai chiamando fdentro di sé

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

Per informazione di tutti, mi trovo improvvisamente in questo con R 3.6.1 su Windows 7 (64 bit). Non era un problema prima, e ora i limiti dello stack sembrano spuntare ovunque, quando provo a "salvare (.)" I dati o anche a fare un "save.image (.)". È come se la serializzazione stesse spazzando via queste pile.

Sto seriamente pensando di tornare a 3.6.0. Non è successo lì.


1

Il mio è forse un caso più unico, ma può aiutare i pochi che hanno questo problema esatto:

Il mio caso non ha assolutamente nulla a che fare con l'utilizzo dello spazio, tuttavia R ha dato:
C stack usage is too close to the limit

Avevo una funzione definita che è un aggiornamento della funzione di base:

saveRDS ()

Ma,
accidentalmente, questa funzione definita è stata chiamata saveRDS()invece di safe_saveRDS().
Quindi, oltre quella definizione, quando il codice è arrivato alla linea che effettivamente utilizza saveRDS(...)(che chiama la versione base originale, non quella aggiornata), ha dato l'errore di cui sopra e si è schiantato.

Quindi, se ricevi quell'errore quando chiami una funzione di salvataggio, controlla se non l'hai accidentalmente investito.


0

Come ha scritto Martin Morgan ... Il problema è che vai troppo in profondità nella ricorsione. Se la ricorsione non converge affatto, è necessario interromperla da soli. Spero che questo codice funzioni, perché non è stato testato. Tuttavia almeno il punto dovrebbe essere chiaro qui.

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

Un altro modo per causare lo stesso problema:

library(debug)
mtrace(lapply)

La chiamata ricorsiva non è così ovvia qui.


0

Se stai usando plot_ly controlla quali colonne stai passando. Sembra che per le colonne POSIXdt / ct, devi usare as.character () prima di passare a plotly o ottieni questa eccezione!


0

Spesso includo una source("path/to/file/thefile.R")riga commentata nella parte superiore di uno script R, ad esempio thefile.R, così posso facilmente copiarla e incollarla nel terminale per eseguirla. Ottengo questo errore se dimentico di commentare la riga, poiché l'esecuzione del file esegue il file, che esegue il file, che esegue il file, ...

Se questa è la causa, la soluzione è semplice: commenta la riga.


0

Non sono sicuro se stiamo elencando i problemi qui, ma a me è successo con leaflet(). Stavo cercando di mappare un dataframe in cui una datecolonna era di classe POSIXlt. Tornando alla POSIXctrisoluzione del problema.


0

Su Linux, ho aumentato in modo permanente la dimensione dello stack e delle memorie memlock in questo modo:

sudo vi /etc/security/limits.conf 

Quindi, aggiungi le seguenti righe alla fine del file.

* soft memlock unlimited
* hard memlock unlimited

* soft stack unlimited
* hard stack unlimited
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.