メモリ消費量の爆発的増加
Google Colaboratory の python 3 で動画作成のために約4万枚の画像作成を実行したところ、ある時点で「メモリ消費量過大でシステムがクラッシュします。ランタイム(~プログラムの実行?)を停止して下さい。」という旨の表示が出て、その後停止してしまった。
この現象には再現性があり、メモリ消費量を測定すると、以下のように変化し、破綻していた。
およそ7000ステップまでに Inactive なメモリが増加し、フリーなメモリが全部消費される。(これもおかしい)
Active なメモリは微増しており、10000ステップを超えると爆発的に増加し、ランタイムが破綻する。
計測は、「cat /proc/meminfo」を python 上で実行した。
- result = subprocess.run('cat /proc/meminfo |egrep -e "Active:|Inactive:|MemFree:"',shell =True,stdout = subprocess.PIPE, stderr = subprocess.PIPE)
- print(result.stdout.decode("utf8"))
対処した結果
データ点の不足は、手動で整形するのが面倒だったため。疑問なら自分で確認。 |
一方、対処した場合のメモリ消費量がこちらの図になる。
Active なメモリはほぼ安定している(初期値0.134, 最終値0.142, [1e+7 kB])
Inactive なメモリの増加もずっと緩やかである。 (これも減らせる?)
より多回数の作図でも安定しそうな挙動になった。
対処方法
今回、Google Colaboratory で実行した対処方法は、次のコマンドの青地部分。
- import matplotlib
- import matplotlib.pyplot as plt
- matplotlib.interactive(False)
参照した記事は「Memory leak with %matplotlib inline #7270」、この対処方法についてはページの下のほうに書かれている。
この記事のもともとの主旨は、「【発見】jupyter notebookでグラフを表示させるための、’%matplotlib inline’ というおまじないを残したままで大量の画像を作成し、保存すると、メモリリーク(メモリが余計に消費される)する模様」。
この場合は、’%matplotlib inline’をコメントアウトすれば対処可能だが、Google Colaboratory では ’%matplotlib inline’ を書いた記憶がなく、こちらの方法を採用した。
'matplotlib.interactive(False)' の挙動を理解していないのは不安要素だが、こいつが色々変数を保持している模様。
他にやった事
今回の爆発的なメモリ消費には無効だったが、次の3点を実行した。
- plt.close()で作画ウインドウを閉じる。
- 「del, gc.collect()」で変数のメモリを解放する。
- time.sleep(1)で、ファイルの書き込みに余裕をもたせる。
plt.close()で作図ウインドウを閉じないと、次々にウインドウを作ってメモリを消費してしまう。(これはいつでも実行すべき)
「del, gc.collect()」で、すでに使用したものの今後は使うあてのない、大量のメモリを消費している変数を解放した。
また、プログラムのバグが悪さをしてるかもと思い、繰り返し部分で消去可能な変数を全て消去、解放した。
これはメモリのやりくりには有効。
最後は、ファイルの書き込み遅延によるメモリ消費を疑って、スリープで時間を飛ばした。(休み無しで働かされるシステムを自分だと思えば、休憩時間を与えたくなるだろう)
plt.close()は効いていたはずだが、gc.collect() と sleep を使っても、メモリの爆発的消費は起こってしまった。
今回、他に参照した記事は以下のとおり。
・Jupyterのmatplotlib inlineのメモリリークバグ(猫になりたい)
・%matplotlib inlineについて(科学やら技術やら)
・【python】pythonでメモリ不足になったときにすること(静かなる名辞)
太陽物理でもsunpyで画像作成する際にはご注意を。
0 件のコメント:
コメントを投稿