Matplotlib에서 많은 양의 이미지를 출력 할 때 메모리 누수 문제를 어떻게하고 싶습니까?

12492 단어 파이썬matplotlib

개요



Matplotlib를 사용하여 데이터를 시각화하고 이미지를 출력하는 것은 적지 않을 것이다. 그 때 savefig를 사용하여 이미지를 출력하면 약간의 메모리 누수가 일어나 버리는 것 같다.
수백장~수천장 정도라면 특별히 문제 없지만, 상당히 대량의 데이터에 대해 수만장~수십만장의 화상을 밤새 출력하고 싶은 경우 등에 문제가 된다.

운영 환경



파이썬: 3.7.7
Matplotlib: 3.2.2

조사



다음 코드를 사용하여 메모리 증가량을 조사했습니다.
import os
import numpy as np
import datetime as dt
import matplotlib.pyplot as plt
import psutil

#計測用データ
memory_start = psutil.virtual_memory().used
time_start = dt.datetime.now()
fw = open('./計測ログ.csv','w')
fw.write('i,time_delta[s],memory[KB]\n')

#1万枚出力させる
for i in range(10000):
    #適当な2種類のデータを生成
    size = 10000
    x1 = np.random.randn(size)
    y1 = 0.5*x1 + 0.5**0.5*np.random.randn(size)
    x2 = np.random.randn(size)
    y2 = np.random.randn(size)

    #グラフを初期化し散布図を作成
    fig, ax = plt.subplots(figsize=(8,8))
    ax.scatter(x1, y1, alpha=0.1, color='r', label='data1')
    ax.scatter(x2, y2, alpha=0.1, color='g', label='data2')

    #ラベル・凡例をつける
    ax.set_xlabel('X')
    ax.set_ylabel('Y')
    ax.legend(loc='upper right')

    #画像出力
    plt.savefig('./output/{:05}.png'.format(i))

    #グラフデータを解放する※
    #plt.clf()
    #plt.cla()
    plt.close()

    #開始時からのメモリ増加量と1ループの時間を計測
    memory_delta = psutil.virtual_memory().used - memory_start
    time_end = dt.datetime.now()
    time_delta = time_end - time_start
    time_start = time_end
    fw.write('{},{},{}\n'.format(i+1, time_delta.microseconds/1e6, memory_delta/1e3))

fw.close()

또한, 그래프의 메모리 해방을 행할 때, close만 실시하는 경우와 cla, clf를 행하고 나서 close한 경우에서 계측했다.



close만의 경우보다 cla, clf를 전에 하는 쪽이 메모리의 증가량은 절반 정도로 억제되고 있다.
그러나 두 경우 모두 증가 할 수 있음을 확인할 수 있습니다.

어떻게?



몇 장의 화상을 출력해도 메모리를 증가시키지 않으려면 어떻게 하면 좋을까?
여러가지 시험한 결과 이하와 같이 코드를 재기록하는 것으로 메모리 누수를 억제해,
게다가 제대로 화상의 출력을 행할 수 있었다.
#初めに初期化を1回だけ行う
fig, ax = plt.subplots(figsize=(8,8))

for i in range(10000):
    #適当な2種類のデータを生成
    x1 = np.random.randn(size)
    y1 = 0.5*x1 + 0.5**0.5*np.random.randn(size)
    x2 = np.random.randn(size)
    y2 = np.random.randn(size)

    ax.scatter(x1, y1, alpha=0.1, color='r', label='data1')
    ax.scatter(x2, y2, alpha=0.1, color='g', label='data2')

    ax.set_xlabel('X')
    ax.set_ylabel('Y')    
    ax.legend(loc='upper right')

    plt.savefig('./output/{:05}.png'.format(i))

    #claのみ行う
    #clf,closeを行ってしまうとその後グラフに書き込めなくなってしまう
    #逆にclaを行わないと前の画像にどんどん重なってしまう   
    plt.cla()




이미지 사이즈를 도중에 바꾸고 싶은 등이 없으면 아마 어떤 그래프라도 이것으로 대응할 수 있는 것은 아닐까 생각하지만 그다지 확신은 없기 때문에 이용할 때는 주의.

좋은 웹페이지 즐겨찾기