Python matplotlib:指定图形大小时未释放内存

发布于 2024-09-18 00:41:20 字数 1077 浏览 5 评论 0原文

我正在使用 matplotlib 生成许多数值模拟结果图。这些图用作视频中的帧,因此我通过重复调用与此类似的函数来生成其中的许多图:

from pylab import *

def plot_density(filename,i,t,psi_Na):  
    figure(figsize=(8,6))
    imshow(abs(psi_Na)**2,origin = 'lower')
    savefig(filename + '_%04d.png'%i)
    clf()

问题是,每次调用时,python 进程的内存使用量都会增加几兆字节这个功能。例如,如果我用这个循环调用它:

if __name__ == "__main__":
    x = linspace(-6e-6,6e-6,128,endpoint=False)
    y = linspace(-6e-6,6e-6,128,endpoint=False)
    X,Y = meshgrid(x,y)
    k = 1000000
    omega = 200
    times = linspace(0,100e-3,100,endpoint=False)
    for i,t in enumerate(times):
        psi_Na = sin(k*X-omega*t)
        plot_density('wavefunction',i,t,psi_Na)
        print i

那么 ram 使用量会随着时间增长到 600MB。然而,如果我注释掉函数定义中的 figure(figsize=(8,6)) 行,那么 ram 使用量将稳定在 52MB。 (8,6) 是默认的图形大小,因此两种情况都会生成相同的图像。我想在不耗尽内存的情况下根据我的数值数据制作不同大小的图。我如何强制 python 释放这些内存?

我已经尝试过 gc.collect() 每个循环来强制垃圾回收,并且我已经尝试过 f = gcf() 来获取当前数字,然后 del f 删除它,但无济于事。

我在 64 位 Ubuntu 10.04 上运行 CPython 2.6.5。

I'm using matplotlib to generate many plots of the results of a numerical simulation. The plots are used as frames in a video, and so I'm generating many of them by repeatedly calling a function similar to this one:

from pylab import *

def plot_density(filename,i,t,psi_Na):  
    figure(figsize=(8,6))
    imshow(abs(psi_Na)**2,origin = 'lower')
    savefig(filename + '_%04d.png'%i)
    clf()

The problem is that the memory usage of the python process grows by a couple of megabytes with every call to this function. For example if I call it with this loop:

if __name__ == "__main__":
    x = linspace(-6e-6,6e-6,128,endpoint=False)
    y = linspace(-6e-6,6e-6,128,endpoint=False)
    X,Y = meshgrid(x,y)
    k = 1000000
    omega = 200
    times = linspace(0,100e-3,100,endpoint=False)
    for i,t in enumerate(times):
        psi_Na = sin(k*X-omega*t)
        plot_density('wavefunction',i,t,psi_Na)
        print i

then the ram usage grows with time to 600MB. If however I comment out the line figure(figsize=(8,6)) in the function definition, then the ram usage stays steady at 52MB. (8,6) is the default figure size and so identical images are produced in both cases. I'd like to make different sized plots from my numerical data without running out of ram. How might I force python to free up this memory?

I've tried gc.collect() each loop to force garbage collection, and I've tried f = gcf() to get the current figure and then del f to delete it, but to no avail.

I'm running CPython 2.6.5 on 64 bit Ubuntu 10.04.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

君勿笑 2024-09-25 00:41:20

来自 pylab.figure 的文档字符串:

In [313]: pylab.figure?

如果您要创建许多图形,请制作
确保您明确调用“关闭”
您没有使用的数字,因为
这将使 pylab 能够正确地
清理内存。

所以也许可以尝试:

pylab.close()     # closes the current figure

From the docstring for pylab.figure:

In [313]: pylab.figure?

If you are creating many figures, make
sure you explicitly call "close" on
the figures you are not using, because
this will enable pylab to properly
clean up the memory.

So perhaps try:

pylab.close()     # closes the current figure
吹泡泡o 2024-09-25 00:41:20

关闭一个数字绝对是一个选择,但是,重复多次,这很耗时。我的建议是拥有一个持久的图形对象(通过 静态函数变量,或作为附加函数参数)。如果该对象是 fig,则该函数将在每个绘图周期之前调用 fig.clf()

from matplotlib import pylab as pl
import numpy as np

TIMES = 10
x = np.linspace(-10, 10, 100)
y = np.sin(x)
def withClose():
    def plotStuff(i):
        fig = pl.figure()
        pl.plot(x, y + x * i, '-k')
        pl.savefig('withClose_%03d.png'%i)
        pl.close(fig)
    for i in range(TIMES):
        plotStuff(i)


def withCLF():
    def plotStuff(i):
        if plotStuff.fig is None:
            plotStuff.fig = pl.figure()
        pl.clf()
        pl.plot(x, y + x * i, '-')
        pl.savefig('withCLF_%03d.png'%i)
    plotStuff.fig = None

    for i in range(TIMES):
        plotStuff(i)

这是时间值

In [7]: %timeit withClose()
1 loops, best of 3: 3.05 s per loop

In [8]: %timeit withCLF()
1 loops, best of 3: 2.24 s per loop

Closing a figure is definitely an option, however, repeated many times, this is time consuming. What I suggest is to have a single persistent figure object (via static function variable, or as additional function argument). If that object is fig, the function will then call fig.clf() before each plotting cycle.

from matplotlib import pylab as pl
import numpy as np

TIMES = 10
x = np.linspace(-10, 10, 100)
y = np.sin(x)
def withClose():
    def plotStuff(i):
        fig = pl.figure()
        pl.plot(x, y + x * i, '-k')
        pl.savefig('withClose_%03d.png'%i)
        pl.close(fig)
    for i in range(TIMES):
        plotStuff(i)


def withCLF():
    def plotStuff(i):
        if plotStuff.fig is None:
            plotStuff.fig = pl.figure()
        pl.clf()
        pl.plot(x, y + x * i, '-')
        pl.savefig('withCLF_%03d.png'%i)
    plotStuff.fig = None

    for i in range(TIMES):
        plotStuff(i)

Here is the timing values

In [7]: %timeit withClose()
1 loops, best of 3: 3.05 s per loop

In [8]: %timeit withCLF()
1 loops, best of 3: 2.24 s per loop
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文