web-dev-qa-db-ja.com

gc()がメモリを解放しないのはなぜですか?

Windows 64bit-computer64 GB RAMでシミュレーションを実行します。メモリ使用量が55%に達し、シミュレーションの実行が完了した後、rm(list=ls())に続いてdouble gc()で作業スペース内のすべてのオブジェクトを削除します。

これは次のシミュレーション実行に十分なメモリを解放すると想定していましたが、実際にはメモリ使用量1%だけ減少です。多くの異なるフォーラムを参照して満足のいく説明を見つけることができませんでした。

"オペレーティングシステムによっては、解放されたメモリがオペレーティングシステムに返されず、プロセススペースに保持される場合があります。"

次に関する情報を検索したい:

  • 1)どのOSおよびどの条件下で解放されたメモリがOSに返されないか、および
  • 2)Rを閉じてから次のシミュレーション実行のために再起動する以外の方法がある場合
56
user7417

メモリ使用量をどのように確認しますか?通常、仮想マシンは、データの保存に使用するメモリの一部を割り当てます。割り当てられたものの一部は未使用で、空きとしてマークされている場合があります。 GCは、他の場所から参照されていないデータを検出し、対応するメモリチャンクを未使用としてマークすることで、このメモリがOSに解放されることを意味しません。それでもVMの観点から見ると、さらなる計算に使用できる空きメモリが増えています。

他の人が尋ねたように、メモリ不足エラーが発生しましたか?そうでなければ、心配することは何もありません。

編集: This および this は、Rでのメモリ割り当てとガベージコレクションの動作を理解するのに十分なはずです。

最初のドキュメントから:

時々、未使用のページを解放してオペレーティングシステムに戻そうとすることがあります。ページが解放されると、R_MaxKeepFracに各クラスに割り当てられたノードの数を掛けた数に等しい空きノードの数が保持されます。この要件を満たすために不要なページがリリースされます。 R_PageReleaseFreqレベル1またはレベル2のコレクションごとに、ページを解放しようとします。

EDIT2:

使用済みメモリを確認するには、verboseをTRUEに設定してgc()を実行してみてください。

gc(verbose=T)

メモリに10'000'000整数の配列がある場合の結果は次のとおりです。

Garbage collection 9 = 1+0+8 (level 2) ... 
10.7 Mbytes of cons cells used (49%)
40.6 Mbytes of vectors used (72%)
          used (Mb) gc trigger (Mb) max used (Mb)
Ncells  198838 10.7     407500 21.8   350000 18.7
Vcells 5311050 40.6    7421749 56.7  5311504 40.6

そして、それはそれへの参照を破棄した後です:

Garbage collection 10 = 1+0+9 (level 2) ... 
10.7 Mbytes of cons cells used (49%)
2.4 Mbytes of vectors used (5%)
         used (Mb) gc trigger (Mb) max used (Mb)
Ncells 198821 10.7     407500 21.8   350000 18.7
Vcells 310987  2.4    5937399 45.3  5311504 40.6

ご覧のとおり、Vcellsが使用するメモリは40.6Mbから2.4Mbに減少しました。

23
Ivan Koblik

Rガベージコレクタは、次の(それほどではない)微妙な方法で不完全です。オブジェクトを移動するしない(つまり、しないcompactメモリ)Cライブラリとの相互作用の方法のため。 (一部の その他 言語/実装もこれに悩まされますが、 その他 は、Cとの対話も必要ですが、 世代別GCの圧縮を管理しますnotはこの問題に苦しんでいます)。

これは、破棄されたメモリの小さなチャンクと、より永続的なオブジェクトの大きなチャンクを順番に割り当てる場合(これは文字列/正規表現処理を行うときの一般的な状況です)、メモリは 断片化されます とガベージコレクタそれについては何もできません。メモリは解放されますが、空きチャンクが短すぎるため再利用できません。

問題を修正する唯一の方法は、必要なオブジェクトを保存し、Rを再起動して、オブジェクトをリロードすることです。

rm(list=ls())を実行しているため、つまりオブジェクトを必要としないため、何も保存およびリロードする必要はありません。そのため、解決策はまさに回避したいことです-R

PS。ガベージコレクションは非常に重要なトピックです。たとえば、 Rubyは20年にわたって5つの(!)異なるGCアルゴリズムを使用しました 。 Java Sun / Oracle および [〜#〜] ibm [〜#〜] 費やしたmany Programmer-yearsGCのそれぞれの実装について。一方、RとPythonはGCが粗末です-誰も必要な人年を投資する手間がかからないので、非常に人気があります。それは 悪い方が良い あなたにとって。

PPS。関連: R: `strsplit`を使用したメモリ不足

28
sds