Error: el uso de la pila de C está demasiado cerca del límite

86

Estoy intentando ejecutar un código recursivo bastante profundo en R y me sigue dando este error:

Error: el uso de la pila de C está demasiado cerca del límite

Mi salida CStack_info()es:

Cstack_info()
    size    current  direction eval_depth 
67108864       8120          1          2 

Tengo mucha memoria en mi máquina, solo estoy tratando de averiguar cómo puedo aumentar CStack para R.

EDITAR: Alguien pidió un ejemplo reproducible. Aquí hay un código de muestra básico que causa el problema. Ejecutando f (1,1) varias veces obtendrá el error. Tenga en cuenta que ya configuré --max-ppsize = 500000 y las opciones (expresiones = 500000), por lo que si no las configura, es posible que obtenga un error sobre una de esas dos cosas. Como puede ver, la recursividad puede ser bastante profunda aquí y no tengo idea de cómo hacer que funcione de manera consistente. Gracias.

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)
}
usuario2045093
fuente
1
Esta pregunta sugiere quizásoptions(expressions = somethinglarge)
mnel
@mnel La profundidad de anidación de la expresión, la pila de protección del puntero y la pila de C son tres cosas separadas (pero relacionadas).
zwol
Muchas gracias por tu pronta respuesta, Zack. Sin embargo, creo que su respuesta puede ser para un sistema operativo Linux. Actualmente estoy ejecutando Windows 7 de 64 bits, ¿eso cambia las cosas en absoluto? Gracias de nuevo por cualquier ayuda.
user2045093
2
Buscar en Google el mensaje de error muestra que, en el pasado, esto generalmente ha sido un error en el código de usuario, por lo que probablemente debería reducir su problema a un ejemplo simple reproducible y publicarlo aquí.
Martin Morgan
2
No estoy seguro de que haya ningún error en el código. Este es simplemente un caso de probabilidades que, en teoría, podrían terminar con una recursividad infinita. f (1,1) es básicamente lanzar una moneda. Podría seguir subiendo cabezas para siempre. Para una condición en la que el nivel de recursividad es desconocido e ilimitado, es mejor que se le ocurra algo más iterativo, utilizando la memorización de los resultados de sample () anteriores para informar operaciones futuras. Entonces, lo único que corre el riesgo es quedarse sin memoria vectorial, o disco, dependiendo de dónde esté almacenando su acumulación de resultados. La recursividad puede ser costosa y frágil.
Robert Casey

Respuestas:

56

El tamaño de la pila es un parámetro del sistema operativo, ajustable por proceso (ver setrlimit(2)). No puede ajustarlo desde dentro de R hasta donde yo sé, pero puede ajustarlo desde el shell antes de iniciar R, con el ulimitcomando. Funciona así:

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

8388608 = 1024 * 8192; R imprime el mismo valor que ulimit -s, pero en bytes en lugar de kilobytes.

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

Para hacer un ajuste permanente a esta configuración, agregue el ulimitcomando a su archivo de inicio de shell, para que se ejecute cada vez que inicie sesión. No puedo dar instrucciones más específicas que eso, porque depende exactamente del shell que tenga y esas cosas. Tampoco sé cómo hacerlo para iniciar sesión en un entorno gráfico (que será relevante si no está ejecutando R dentro de una ventana de terminal).

zwol
fuente
12
... o simplemente configúrelo en unlimited.
Paul Hiemstra
1
El RAppArmorpaquete ofrece una interfaz para setrlimit(2). Esta funcionalidad puede estar disponible en el ulimitpaquete en algún momento.
krlmlr
2
Esta función ya no existe en el paquete RAppArmor . ¿Alguna idea de a dónde fue?
CoderGuy123
2
¿Cuál es la solución para Windows?
S.Perera
2
Cambiar el límite no resolverá esto. Una función recursiva simplemente continuará ejecutándose hasta que se alcance el límite superior.
Tom Kelly
27

Sospecho que, independientemente del límite de pila, terminarás con recursiones demasiado profundas. Por ejemplo, con lambda = Inf, f (1) conduce a una recursividad inmediata, de forma indefinida. La profundidad de la recursividad parece ser un paseo aleatorio, con alguna probabilidad r de ir más profundo, 1 - r de terminar la recursión actual. Cuando llegue al límite de la pila, habrá realizado una gran cantidad de pasos 'más profundos'. Esto implica que r> 1/2, y la gran mayoría de las veces continuará recurriendo.

Además, parece que es casi posible derivar una solución analítica o al menos numérica incluso frente a la recursividad infinita. Se puede definir p como la probabilidad de que f (1) == 1, escribir expresiones implícitas para los estados 'secundarios' después de una sola iteración, equipararlas con p y resolver. Entonces, p puede usarse como la probabilidad de éxito en un solo sorteo de una distribución binomial.

Martín Morgan
fuente
1
En realidad, aquí hay una respuesta correcta oculta: asegúrese de no sumergirse tanto en la recusión ...
Kamil S Jaron
En mi caso, el error se debe a la obtención del mismo script R varias veces (es decir, en varios scripts R) en mi proyecto.
Good Will
14

Este error no se debe a la memoria sino a la recursividad . Una función se llama a sí misma. Para ilustrar el punto, aquí hay un ejemplo mínimo de 2 funciones que se llaman entre sí:

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

Error: el uso de la pila C 7971600 está demasiado cerca del límite

Las funciones continuarán llamándose recursivamente y, en teoría, nunca se completarán. Solo las verificaciones dentro de su sistema evitan que esto ocurra indefinidamente y consuma todos los recursos informáticos de su máquina. Debe modificar las funciones para asegurarse de que no se llamen a sí mismas (o entre sí) de forma recursiva.

Tom Kelly
fuente
10

Esto me sucedió por una razón completamente diferente. Creé accidentalmente una cadena superlarga mientras combinaba dos columnas:

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

en vez de

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

Me tomó una eternidad averiguarlo, ya que nunca esperé que la pasta hubiera causado el problema.

Alex Joseph
fuente
Lo mismo aquí, pero estaba haciendo un resumen. Lo tenía como esto: summarize( states = paste0(state,collapse=', ') ). Cuando debería haber hecho algo como: summarize( states = paste0(sort(unique(state)),collapse=', ') ). El objetivo era obtener una lista separada por comas de estados únicos disponibles para cada subgrupo.
Richard DiSalvo
4

Encontré el mismo problema de recibir el error "El uso de la pila de C está demasiado cerca del límite" (aunque para otra aplicación que no sea la indicada por user2045093 arriba). Probé la propuesta de zwol pero no funcionó.

Para mi propia sorpresa, pude resolver el problema instalando la versión más reciente de R para OS X (actualmente: versión 3.2.3) así como la versión más reciente de R Studio para OS X (actualmente: 0.99.840), ya que estoy trabajando con R Studio.

Con suerte, esto también puede ser de ayuda para usted.

GRAJILLA
fuente
1
Cambié a una versión superior de R. Funcionó una vez, pero el error reapareció y ahora es consistente. ¡Ayuda!
murphy1310
2

Un problema aquí puede ser que estás llamando fdentro de sí mismo

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=) ?
Colin FAY
fuente
1

Para la información de todos, de repente me encuentro con esto con R 3.6.1 en Windows 7 (64 bits). No era un problema antes, y ahora los límites de la pila parecen aparecer en todas partes, cuando intento "guardar (.)" Datos o incluso hacer un "guardar.imagen (.)". Es como si la serialización estuviera acabando con estas pilas.

Estoy considerando seriamente volver a 3.6.0. No sucedió allí.


fuente
1

El mío es quizás un caso más singular, pero puede ayudar a los pocos que tienen este problema exacto:

Mi caso no tiene absolutamente nada que ver con el uso del espacio, aún así R dio el:
C stack usage is too close to the limit

Tenía una función definida que es una actualización de la función base:

saveRDS ()

Pero,
accidentalmente, esta función definida fue llamada en saveRDS()lugar de safe_saveRDS().
Por lo tanto, más allá de esa definición, cuando el código llegó a la línea que realmente usa saveRDS(...)(que llama a la versión base original, no a la actualizada), dio el error anterior y se aplastó.

Por lo tanto, si recibe ese error al llamar a alguna función de guardado, vea si no lo ejecutó accidentalmente.

Tony
fuente
0

Como escribió Martin Morgan ... El problema es que te adentras demasiado en la recursividad. Si la recursividad no converge en absoluto, debe romperla por su cuenta. Espero que este código funcione, porque no está probado. Sin embargo, al menos un punto debería quedar claro aquí.

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)
}
Kamil S Jaron
fuente
0

Otra forma de causar el mismo problema:

library(debug)
mtrace(lapply)

La llamada recursiva no es tan obvia aquí.

Quigi
fuente
0

Si está utilizando plot_ly, compruebe qué columnas está pasando. Parece que para las columnas POSIXdt / ct, debe usar as.character () antes de pasar a plotly o obtendrá esta excepción.

Fred Johnson
fuente
0

A menudo incluyo una línea comentada source("path/to/file/thefile.R")en la parte superior de un script de R, por ejemplo thefile.R, para poder copiar y pegar esto fácilmente en la terminal para ejecutarlo. Recibo este error si olvido comentar la línea, ya que ejecutar el archivo ejecuta el archivo, que ejecuta el archivo, que ejecuta el archivo, ...

Si esa es la causa, la solución es simple: comente la línea.

bstock
fuente