101

Rでかなり深い再帰コードを実行しようとしていますが、このエラーが発生し続けます:

エラー: C スタックの使用量が限界に近すぎます

私の出力CStack_info()は次のとおりです。

Cstack_info()
    size    current  direction eval_depth 
67108864       8120          1          2 

私のマシンには十分なメモリがあります.RのCStackを増やす方法を見つけようとしています.

編集:誰かが再現可能な例を求めました。問題の原因となる基本的なサンプル コードを次に示します。f(1,1) を数回実行すると、エラーが発生します。--max-ppsize = 500000 と options(expressions=500000) を既に設定しているので、これらを設定しないと、代わりにこれら 2 つのいずれかについてエラーが発生する可能性があることに注意してください。ご覧のとおり、再帰はここでかなり深くなる可能性があり、それを一貫して機能させる方法がわかりません。ありがとう。

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

15 に答える 15

62

スタック サイズはオペレーティング システムのパラメータであり、プロセスごとに調整できます (「 」を参照setrlimit(2))。私の知る限り、R 内から調整することはできませんが、ulimitコマンドを使用して、R を開始する前にシェルから調整することができます。それはこのように動作します:

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

8388608 = 1024 * 8192; R は と同じ値を出力しulimit -sていますが、キロバイトではなくバイト単位です。

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

この設定を恒久的に調整するには、ulimitコマンドをシェルの起動ファイルに追加します。これにより、ログインするたびにコマンドが実行されます。それ以上の具体的な指示はできません。これは、使用しているシェルやその他のものに依存するためです。また、グラフィカル環境にログインする方法もわかりません (これは、ターミナル ウィンドウ内で R を実行していない場合に関係します)。

于 2013-02-06T00:20:11.127 に答える
28

スタック制限に関係なく、深すぎる再帰になってしまうのではないかと思います。たとえば、lambda = Inf の場合、f(1) は即時の再帰を無期限に実行します。再帰の深さはランダム ウォークのようであり、r の確率でさらに深くなり、1 - r で現在の再帰が終了します。スタック制限に達するまでに、多数のステップを「より深く」作成しています。これは、r > 1 / 2 であることを意味し、ほとんどの場合、再帰を続けます。

また、無限再帰に直面しても、解析的または少なくとも数値的な解を導出することはほとんど可能であるように思われます。f(1) == 1 である確率として p を定義し、1 回の反復の後に「子」状態の暗黙の式を記述し、これらを p と等しくして、解くことができます。p は、二項分布からの 1 回の抽選で成功する確率として使用できます。

于 2013-02-06T07:47:53.517 に答える
12

これはまったく別の理由で私に起こりました。2 つの列を結合しているときに、誤って非常に長い文字列を作成してしまいました。

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

それ以外の

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

ペーストが問題を引き起こすとは思っていなかったので、それを理解するのに永遠にかかりました.

于 2015-04-22T08:21:29.523 に答える
5

「Cスタックの使用量が限界に近すぎます」というエラーを受け取るという同じ問題が発生しました(上記のuser2045093が述べたものとは別のアプリケーションですが)。zwol の提案を試みましたが、うまくいきませんでした。

驚いたことに、OS X 用の R の最新バージョン (現在: バージョン 3.2.3) と OS X 用の R Studio の最新バージョン (現在: 0.99.840) をインストールすることで問題を解決できました。 Rスタジオで作業しています。

うまくいけば、これもあなたに役立つかもしれません。

于 2015-12-31T16:06:15.660 に答える
2

fここでの 1 つの問題は、それ自体の内部で呼び出している可能性があります。

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=) ?
于 2018-02-26T17:49:18.180 に答える
1

Linux では、こうすることで、スタックと memlock メモリのサイズを永続的に増やしました。

sudo vi /etc/security/limits.conf 

次に、ファイルの末尾に次の行を追加します。

* soft memlock unlimited
* hard memlock unlimited

* soft stack unlimited
* hard stack unlimited
于 2020-11-26T10:10:56.753 に答える
0

Martin Morgan が書いたように... 問題は、再帰の内部に深く入り込みすぎることです。再帰がまったく収束しない場合は、自分で分解する必要があります。テストされていないため、このコードが機能することを願っています。ただし、少なくともポイントはここで明確にする必要があります。

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)
}
于 2015-05-12T17:56:43.827 に答える