plt.close()만으로는 메모리가 해제되지 않는 경우가 있다

6310 단어 파이썬matplotlib

추가 2



이 기사에는 범용적인 대처법이 기재되어 있습니다.
matplotlib.pyplot의 메모리 누수 해결 - Qiita

주의(추기 1)



이 기사에서 소개하는 실험에서는 plt.clf() → plt.close() 그러면 메모리가 해제된다는 결과가 되었습니다. 그러나, plt 의 사용법에 따라서는, plt.clf() → plt.close() 라고 해도 메모리가 해방되지 않는 경우가 있는 것이 나중에 판명되었습니다. 그 때문에, 이 기사는 plt 에 있어서의 메모리 해방의 거동을 이해하는데 있어서의 참고로서 이용해 주시면 좋겠습니다.

덧붙여 사례로서는, plt.tight_layout() 이나 plt.savefig() 를 하면(자) 메모리가 해방되지 않는 것 같습니다. 이 경우, 만약 Jupyter상에서 실행하고 있는 것이면, 다른 셀로 gc.collect() 를 하는 것으로, kernel을 재기동하지 않고 대부분의 메모리를 해방할 수 있는 것을 필자는 확인하고 있습니다. (그러나 같은 셀에서 plt.clf() → plt.close() 를 한 직후에 gc.collect() 를 하면 메모리가 해제되지 않았습니다.)

요약


# NG
# メモリが解放されない
plt.close()

# OK
# メモリが解放される
plt.clf()
plt.close()

# NG
# 順番を逆にするとメモリが解放されない
# plt.close() で figure を閉じると、描画内容を clear 出来なくなるからだろう。
plt.close()
plt.clf()

경위



한 번에 수천 장의 그래프를 그렸던 곳에 out of memory 오류가 발생했습니다. 매번 plt.close() 를 하고 있었으므로 왜일까라고 생각 이하의 실험 방법으로 조사했습니다. 그 결과, plt.close()만으로는 메모리가 해방되지 않는 것을 알았습니다. 그리고 plt.clf() → plt.close() 그러면 메모리가 해제되는 것을 알았습니다.

실험 방법



메모리 크기가 큰 그래프를 10회 연속으로 플로팅합니다.
각 플롯 종료시의 메모리 사용량을 기록해 두고, 플롯 횟수와 메모리 사용량의 관계를 조사합니다.
이 절차는 다음 4가지 패턴으로 수행됩니다.



후처리 방법


패턴 1
plt.clf()

패턴 2
plt.clf() → plt.close()

패턴 3
plt.close()

패턴 4
plt.close() → plt.clf()


그러나 각 패턴에 대해 매번 커널을 다시 시작합니다. 메모리 사용량의 기준선을 맞추기 위해서입니다.

이 작업을 수행하는 코드는 다음과 같습니다.
import matplotlib.pyplot as plt
import numpy as np
import psutil

mem_ary = []

# 10回プロットする
for i in range(10):

    # メモリサイズが大きいグラフを描画
    x = np.arange(1e7)
    y = np.arange(1e7)
    plt.plot(x, y)

    # ===================================================
    # 以下のパターン1からパターン4のいずれか1つを実行する
    # 残りはコメントアウトする
    # ===================================================

    # パターン1
    plt.clf()

    # パターン2
    plt.clf()
    plt.close()

    # パターン3
    plt.close()

    # パターン4
    plt.close()
    plt.clf

    # ===================================================

    # メモリ使用量を記録
    mem = psutil.virtual_memory().used / 1e9
    mem = round(mem, 1)
    mem_ary.append(mem)

결과와 결론



결과를 그래프에 정리하면 다음과 같습니다.


plt.clf() → plt.close() 만 메모리 사용량이 증가하지 않습니다. 따라서, plt.clf() → plt.close() 로 할 일을 알 수 있습니다.

또, 순서를 반대로 해 plt.close() → plt.clf() 라고 하면 메모리가 해방되지 않게 되어 있습니다. 조심하는 것이 좋습니다. 원인은, 아마 plt.close() 그리고 figure 를 닫으면(자), 묘화 내용을 clear 할 수 없게 되기 때문이라고 생각합니다. (참고: plt.close()의 공식 DOC , plt.clf()의 공식 DOC )

버전



matplotlib : 3.2.1

좋은 웹페이지 즐겨찾기