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


88

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

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

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

Cstack_info()
    size    current  direction eval_depth 
67108864       8120          1          2 

マシンに十分なメモリがあります。CStackforRを増やす方法を見つけようとしています。

編集:誰かが再現可能な例を求めました。問題の原因となる基本的なサンプルコードを次に示します。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)
}

1
この質問はおそらくoptions(expressions = somethinglarge)
mnel 2013

@mnel式のネストの深さ、ポインター保護スタック、およびCスタックは、3つの別個の(ただし関連する)ものです。
zwol 2013

迅速な対応、ザック、どうもありがとうございました。あなたの答えはLinuxOS向けかもしれないと思いますか?私は現在Windows7 64ビットを実行していますが、それによって状況はまったく変わりますか?助けてくれてありがとう。
user2045093 2013

2
エラーメッセージをグーグルで検索すると、これまでは通常ユーザーコードのエラーであったことがわかります。そのため、問題を簡単な再現可能な例に減らして、ここに投稿する必要があります。
マーティンモーガン

2
コードにエラーがあるかどうかはまったくわかりません。これは、理論的には無限再帰になる可能性のある確率の単なるケースです。f(1,1)は基本的にコインを投げています。それは永遠に頭を上げ続ける可能性があります。再帰のレベルが不明で制限がない状態の場合は、以前のsample()の結果をメモ化して将来の操作に通知することで、より反復的なものを考え出すことをお勧めします。その場合、リスクを負う唯一のことは、結果のバックログを保存している場所に応じて、ベクトルメモリまたはディスクが不足することです。再帰は高価で脆弱な場合があります。
ロバートケーシー

回答:


57

スタックサイズはオペレーティングシステムのパラメータであり、プロセスごとに調整可能です(を参照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を実行していない場合に関係します)。


12
...または単にに設定しunlimitedます。
Paul Hiemstra 2013

1
このRAppArmorパッケージは、へのインターフェースを提供しますsetrlimit(2)。この機能はulimit、ある時点でパッケージで利用できるようになる可能性があります。
krlmlr 2016

2
この関数は、RAppArmorパッケージには存在しなくなりました。それがどこに行ったのかアイデアはありますか?
coderGuy123 2017

2
Windowsの修正は何ですか?
S.Perera

2
制限を変更しても、これは解決されません。再帰関数は、上限に達するまで実行を続けます。
トム・ケリー

27

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

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


1
ここに実際には隠された正解があります-再帰にそれほど深くならないようにしてください...–
カミルSジャロン

私の場合、エラーは、プロジェクトで同じRスクリプトを複数回(つまり、複数のRスクリプトで)ソースすることによって発生します。
グッドウィル

15

このエラーはメモリによるものではなく、再帰によるものです。関数がそれ自体を呼び出しています。この点を説明するために、相互に呼び出す2つの関数の最小限の例を次に示します。

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

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

関数は引き続き再帰的に相互に呼び出し、理論的には完了しません。これが無期限に発生し、マシンのすべてのコンピューティングリソースを消費するのを防ぐのは、システム内のチェックだけです。関数を変更して、関数が自分自身(または相互)を再帰的に呼び出さないようにする必要があります。


10

これはまったく別の理由で私に起こりました。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 = "_"))

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


ここでも同じですが、要約を行っていました。私はそれをこのように持っていました: summarize( states = paste0(state,collapse=', ') )。次のようなことをすべきだったとき:summarize( states = paste0(sort(unique(state)),collapse=', ') )。目標は、各サブグループで使用可能な一意の状態のコンマ区切りのリストを取得することでした。
リチャードディサルボ2017

4

「Cスタックの使用量が制限に近すぎます」という同じ問題が発生しました(上記のuser2045093で指定されたものとは別のアプリケーションの場合でも)。zwolの提案を試しましたが、うまくいきませんでした。

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

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


1
Rの上位バージョンに切り替えました。一度は機能しましたが、エラーが再発し、現在は一貫しています。助けて!
murphy13 1018

2

ここでの1つの問題は、自分f自身の内部で呼び出していることです。

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

皆さんの情報として、私はWindows 7(64ビット)のR3.6.1で突然これに遭遇しました。以前は問題ではありませんでしたが、データを「save(。)」しようとしたり、「save.image(。)」を実行したりすると、スタック制限がどこにでも表示されるようになりました。シリアル化がこれらのスタックを吹き飛ばしているようなものです。

3.6.0に戻すことを真剣に検討しています。そこでは起こりませんでした。


1

鉱山はおそらくもっとユニークなケースですが、この正確な問題を抱えている少数の人を助けるかもしれません:

私の場合はスペースの使用量とはまったく関係ありませんが、それでもRは次のように述べています。
C stack usage is too close to the limit

基本関数のアップグレードである定義済み関数がありました。

saveRDS()

しかし、
偶然にも、この定義された関数はのsaveRDS()代わりに呼び出されましたsafe_saveRDS()
したがって、その定義を過ぎて、wihchが実際に使用する行saveRDS(...)(アップグレードされたものではなく、元のベースバージョンを呼び出す)にコードが到達すると、上記のエラーが発生し、クラッシュしました。

したがって、保存関数を呼び出したときにそのエラーが発生した場合は、誤ってそれを実行していないかどうかを確認してください。


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

0

同じ問題を引き起こす別の方法:

library(debug)
mtrace(lapply)

ここでは、再帰呼び出しはそれほど明白ではありません。


0

plot_lyを使用している場合は、渡す列を確認してください。POSIXdt / ct列の場合、plotlyに渡す前にas.character()を使用する必要があるようです。そうしないと、この例外が発生します。


0

source("path/to/file/thefile.R")たとえばthefile.R、Rスクリプトの先頭にコメントアウトされた行を含めることがよくあるので、これをターミナルに簡単にコピーして貼り付けて実行できます。ファイルを実行するとファイルが実行され、ファイルが実行され、ファイルが実行されるため、行をコメントアウトするのを忘れると、このエラーが発生します...

それが原因である場合、解決策は簡単です。行をコメントアウトします。


0

ここに問題を再リストするかどうかはわかりませんが、で発生しましたleaflet()date列がクラスのデータフレームをマップしようとしていましたPOSIXltPOSIXct問題を解決するために元に戻します。


0

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

sudo vi /etc/security/limits.conf 

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

* soft memlock unlimited
* hard memlock unlimited

* soft stack unlimited
* hard stack unlimited
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.