15

ときどき MATLAB スクリプトを開始して、あまりにも多くの図を出力しようとしていることに気付くのが遅すぎることがあります。最終的に私は

スレッド「AWT-EventQueue-0」での例外 java.lang.OutOfMemoryError: Java ヒープ領域

私のマシンで簡単に再現できます

for i=1:inf
  figure;
end

128 MB の Java ヒープの標準設定 ( Preferences / Java Heap Memory ) でクラッシュする前に、約 90 桁に達しますが、ヒープを 256 MB に倍増すると、約 200 桁になります。

Java エラー メッセージを回避する方法はありますか? 別の図に十分なメモリがない場合は、スクリプトがクラッシュするのではなく、通知されるようにしたいと考えています。

figureたぶん、 Java ヒープがどれだけ利用可能かをチェックし、十分なスペースが残っていない場合は新しい図を開くことを拒否するラッパーを (どういうわけか?) 持つことができますか?

アップデート

以下の回答を使用すると、Java のメモリの空き容量を示す素晴らしいグラフが得られます。

figure;plot(freeMem/1E6,'x');ylabel('java.lang.Runtime.getRuntime.freeMemory [MB]');xlabel('作成された空の図の数');

これは、

for i=1:inf
    java.lang.Runtime.getRuntime.gc
    fprintf('%3.0f: %1.0f Byte free\n',i,java.lang.Runtime.getRuntime.freeMemory);
    figure;
end

最初の増加は、ガベージコレクションを呼び出すたびに特定の労力しか行わないことを意味すると思いますか?

更新 2 - 私の解決策

ここで得たヘルプを使用して、組み込みコマンドfigure.mをオーバーロードして呼び出す次のソリューションを実装しました。figure

function varargout=figure(varargin)
memcutoff = 10E6; % keep at least this amount of bytes free
memkeyboard= 3E6; % if memory drops below this, interrupt execution and go to keyboard mode
global refuse_new_figures
if refuse_new_figures
    warning('jb:fig:lowjavamem2','Java WAS memory low -> refusing to create a new figure. To reset, type "global refuse_new_figures ; refuse_new_figures = [];"');
    return
end
freemem=java.lang.Runtime.getRuntime.freeMemory;
if freemem < memcutoff 
    fprintf('Free memory is low (%1.0f Bytes) -> running garbace collector...\n',freemem);
    java.lang.Runtime.getRuntime.gc
end
freemem=java.lang.Runtime.getRuntime.freeMemory;
% fprintf('Free memory is %1.0f Bytes.\n',freemem);
if freemem < memkeyboard
    warning('jb:fig:lowjavamem','Java memory very low -> going into interactive mode. Good luck!');
    keyboard;
end
if freemem < memcutoff
    warning('jb:fig:lowjavamem','Java memory low -> refusing to create a new figure!');
    refuse_new_figures=true;
else
    if nargin > 0
        if nargout > 0
            varargout{1}=builtin('figure',varargin{:});
        else
            builtin('figure',varargin{:});
        end
    else
        if nargout > 0
            varargout{1}=builtin('figure');
        else
            builtin('figure');
        end
    end
end
4

3 に答える 3

6

一般に、Java ヒープ メモリの最大値を使用可能な RAM の約 25% に設定することをお勧めします。これにより、多数の Figure を開くことができます (ただし、無限の数ではありません)。環境設定でこれを行うことができない場合 (たとえば、私のような Mac を使用している場合)、この解決策が役立ちます - 環境設定を上書きします。

リンクされたソリューションは、残りの空き Java メモリの量と、使用可能な合計量も示します。次のコマンドを実行します。

java.lang.Runtime.getRuntime.maxMemory
java.lang.Runtime.getRuntime.totalMemory
java.lang.Runtime.getRuntime.freeMemory 

残念なことに、Figure は一定量の Java メモリを使用しません。空の Figure は、10k ポイントを表示する Figure よりもはるかに少なく、最小化された Figure は最大化された Figure よりも少ないメモリを消費します。ただし、図ごとに必要な平均メモリを見積もることができれば、figureこの図が最後になる可能性があるかどうかをチェックするためのラッパーを実際に作成できます。あるいは/さらに、ラッパー関数で他のすべての図を最小化することもできます(これについては、文書化されていないMatlabを参照してください)。

EDIT @Peter Lawreyが指摘したように、使用可能なメモリ量を確認する前にガベージ コレクションを実行することもできますが、とにかく Matlab がそれを試みるかどうかはわかりません。

于 2011-06-01T12:49:03.863 に答える
2

GC をトリガーして再度確認するのに十分な量がない場合は、空きメモリを確認できます。それでも足りない場合は失敗。1 ~ 10 MB のヘッド ルームを許可することをお勧めします。

Runtime.gc() と Runtime.freeMemory(); を使用できます。

最大メモリを設定しない場合、使用可能なメモリのパーセンテージになります。

于 2011-06-01T12:49:12.990 に答える
1

私は独自の関数 'limfig' で findobj 関数を使用します。imglimit は、一度に開くことを許可する Figure の量を設定します。

function y=limfig
imglimit=15;
if length(findobj('type','figure'))<imglimit
    y=figure; 

else
    'too many figures already open'
    return
end
end

この短いコードを limfig.m として保存し、他のコードで f=figure の代わりに f=limfig 行を使用します。

于 2016-08-16T07:29:35.527 に答える