Erro: o uso da pilha C está muito próximo do limite


86

Estou tentando executar um código recursivo bastante profundo em R e ele continua me apresentando este erro:

Erro: o uso da pilha C está muito próximo do limite

Minha saída CStack_info()é:

Cstack_info()
    size    current  direction eval_depth 
67108864       8120          1          2 

Tenho muita memória em minha máquina, só estou tentando descobrir como posso aumentar o CStack para R.

EDIT: Alguém pediu um exemplo reproduzível. Aqui está um exemplo de código básico que causa o problema. Executando f (1,1) algumas vezes você obterá o erro. Observe que eu já configurei --max-ppsize = 500000 e options (expression = 500000), portanto, se você não configurá-los, poderá obter um erro sobre uma dessas duas coisas. Como você pode ver, a recursão pode ser muito profunda aqui e não tenho ideia de como fazê-la funcionar de forma consistente. Obrigado.

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
Esta pergunta sugere talvezoptions(expressions = somethinglarge)
mês de

@mnel A profundidade de aninhamento de expressão, a pilha de proteção de ponteiro e a pilha C são três coisas separadas (mas relacionadas).
zwol

Muito obrigado pela sua resposta rápida, Zack. Eu acho que sua resposta pode ser para um sistema operacional Linux? No momento, estou executando o Windows 7 de 64 bits. Isso muda as coisas? Obrigado novamente por qualquer ajuda.
user2045093

2
Pesquisar a mensagem de erro no Google mostra que, no passado, isso geralmente era um erro no código do usuário, então você provavelmente deve reduzir seu problema a um exemplo reproduzível simples e postá-lo aqui.
Martin Morgan

2
Não tenho certeza se há um erro no código. Este é simplesmente um caso de probabilidades que poderiam, em teoria, resultar em recursão infinita. f (1,1) é basicamente jogar uma moeda. Pode continuar surgindo cabeças para sempre. Para uma condição em que o nível de recursão é desconhecido e ilimitado, é melhor inventar algo mais iterativo, usando memoização de resultados sample () anteriores para informar operações futuras. Então, a única coisa que você corre o risco é ficar sem memória vetorial, ou disco, dependendo de onde você está armazenando o backlog de resultados. A recursão pode ser cara e frágil.
Robert Casey

Respostas:


56

O tamanho da pilha é um parâmetro do sistema operacional, ajustável por processo (consulte Recursos setrlimit(2)). Você não pode ajustá-lo de dentro de R, tanto quanto eu posso dizer, mas você pode ajustá-lo de shell antes de iniciar R, com o ulimitcomando. Funciona assim:

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

8388608 = 1024 * 8192; R está imprimindo o mesmo valor ulimit -s, mas em bytes em vez de kilobytes.

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

Para fazer um ajuste permanente a esta configuração, adicione o ulimitcomando ao seu arquivo de inicialização do shell, para que seja executado toda vez que você efetuar login. Não posso dar instruções mais específicas do que isso, porque depende exatamente de qual shell você tem e outras coisas. Eu também não sei como fazer isso para entrar em um ambiente gráfico (o que será relevante se você não estiver executando o R dentro de uma janela de terminal).


12
... ou apenas defina como unlimited.
Paul Hiemstra

1
O RAppArmorpacote oferece uma interface para setrlimit(2). Essa funcionalidade pode ficar disponível no ulimitpacote em algum momento.
Krlmlr

2
Esta função não existe mais no pacote RAppArmor . Alguma ideia para onde foi?
CoderGuy123

2
Qual é a correção para o Windows?
S.Perera

2
Alterar o limite não resolverá isso. Uma função recursiva simplesmente continuará a funcionar até que o limite superior seja alcançado.
Tom Kelly

27

Suspeito que, independentemente do limite de pilha, você acabará com recursões muito profundas. Por exemplo, com lambda = Inf, f (1) leva a uma recursão imediata, indefinidamente. A profundidade da recursão parece ser um passeio aleatório, com alguma probabilidade r de se aprofundar, 1 - r de terminar a recursão atual. No momento em que você atingiu o limite de pilha, você deu um grande número de etapas 'mais profundas'. Isso implica que r> 1/2 e, na grande maioria das vezes, você apenas continuará a recursão.

Além disso, parece que é quase possível derivar uma solução analítica ou pelo menos numérica, mesmo em face da recursão infinita. Pode-se definir p como a probabilidade de que f (1) == 1, escrever expressões implícitas para os estados 'filho' após uma única iteração e igualá-los a p e resolver. p pode então ser usado como a chance de sucesso em um único sorteio de uma distribuição binomial.


1
aqui está a resposta correta oculta - certifique-se de não se aprofundar em recusão ...
Kamil S Jaron

No meu caso, o erro é causado pela origem do mesmo script R várias vezes (ou seja, em vários scripts R) no meu projeto.
Boa Vontade,

14

Este erro não é devido à memória , é devido à recursão . Uma função está chamando a si mesma. Para ilustrar o ponto, aqui está um exemplo mínimo de 2 funções que se chamam:

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

Erro: o uso da pilha C 7971600 está muito próximo do limite

As funções continuarão a se chamar recursivamente e, teoricamente, nunca serão concluídas. São apenas verificações em seu sistema que evitam que isso ocorra indefinidamente e consuma todos os recursos de computação de sua máquina. Você precisa alterar as funções para garantir que elas não chamem a si mesmas (ou umas às outras) recursivamente.


10

Isso aconteceu comigo por um motivo completamente diferente. Eu acidentalmente criei uma string superlonga ao combinar duas colunas:

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

ao invés de

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

Levei uma eternidade para descobrir, pois nunca esperei que a pasta tivesse causado o problema.


O mesmo aqui, mas eu estava fazendo um resumo. Eu tinha-o assim: summarize( states = paste0(state,collapse=', ') ). Quando eu deveria ter feito algo como: summarize( states = paste0(sort(unique(state)),collapse=', ') ). O objetivo era obter uma lista separada por vírgulas de estados exclusivos disponíveis para cada subgrupo.
Richard DiSalvo

4

Eu encontrei o mesmo problema de recebimento do erro "O uso da pilha C está muito próximo do limite" (embora para outro aplicativo que não o declarado pelo usuário 2045093 acima). Tentei a proposta de zwol, mas não deu certo.

Para minha própria surpresa, eu poderia resolver o problema instalando a versão mais recente do R para OS X (atualmente: versão 3.2.3), bem como a versão mais recente do R Studio para OS X (atualmente: 0.99.840), já que eu estou trabalhando com R Studio.

Esperançosamente, isso pode ser de alguma ajuda para você também.


1
Mudei para uma versão superior do R. Funcionou uma vez, mas o erro reapareceu e é consistente agora. Socorro!
murphy1310

2

Um problema aqui pode ser que você está chamando fdentro de si

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

Para a informação de todos, de repente estou encontrando isso com R 3.6.1 no Windows 7 (64 bits). Não era um problema antes, e agora os limites de pilha parecem estar surgindo em todos os lugares, quando tento "salvar (.)" Dados ou até mesmo faço um "save.image (.)". É como se a serialização estivesse explodindo essas pilhas.

Estou pensando seriamente em voltar para a versão 3.6.0. Não aconteceu lá.


1

O meu é talvez um caso mais único, mas pode ajudar os poucos que têm este problema exato:

Meu caso não tem absolutamente nada a ver com uso de espaço, ainda R deu o:
C stack usage is too close to the limit

Eu tinha uma função definida que é uma atualização da função de base:

saveRDS ()

Mas,
acidentalmente, essa função definida foi chamada em saveRDS()vez de safe_saveRDS().
Assim, além dessa definição, quando o código chegou à linha que realmente usa saveRDS(...)(que chama a versão base original, não a atualizada), ele deu o erro acima e esmagou.

Portanto, se você está recebendo esse erro ao chamar alguma função de salvamento, veja se não a atropelou acidentalmente.


0

Como Martin Morgan escreveu ... O problema é que você se aprofunda demais na recursão. Se a recursão não convergir, você precisa quebrá-la sozinho. Espero que este código funcione, porque ele não foi testado. No entanto, pelo menos um ponto deve estar claro aqui.

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

Outra forma de causar o mesmo problema:

library(debug)
mtrace(lapply)

A chamada recursiva não é tão óbvia aqui.


0

Se você estiver usando plot_ly, verifique quais colunas você está passando. Parece que para colunas POSIXdt / ct, você tem que usar as.character () antes de passar para plotly ou você obterá esta exceção!


0

Costumo incluir uma source("path/to/file/thefile.R")linha comentada no topo de um script R, por exemplo thefile.R, para que possa copiar e colar facilmente no terminal para executá-lo. Recebo este erro se me esquecer de comentar a linha, uma vez que executar o arquivo executa o arquivo, que executa o arquivo, que executa o arquivo, ...

Se for essa a causa, a solução é simples: comente a linha.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.