matplotlib 在 pcolorfast 上内存溢出

3 投票
1 回答
1062 浏览
提问于 2025-04-16 08:25

问题:

我现在正在从文本文件中加载列数据到numpy数组里,然后绘制这些数据并保存生成的图像。因为这些值总是均匀分布在一个网格上,所以我觉得可以使用pcolorfast。每个数组都是正方形的,通常大小在1024x1024到8192x8192之间。目前,我只关心4096x4096及以下的大小。这项工作需要处理数百个文件,虽然第一个图像能够成功生成,但后续的图像却因为内存错误而崩溃。

未成功的解决方案:

我已经确保按照这里的建议,将rc中的hold设置为False。

限制:

图像必须使用所有的4096x4096的值,不能缩小到1024x1024(正如这里所建议的那样)。

备注:

在每个阶段(创建空数组、加载值、绘图、保存)观察内存使用情况后,我发现数组A在makeFrame完成后仍然占用内存。是否需要明确调用删除它?fig是否需要明确删除,还是pylab会处理这个问题?理想的情况(可能很明显)是内存使用量能回到调用makeFrame()之前的水平。

任何建议都非常感谢。我已经尝试解决这个问题几天了,所以很可能我错过了一些明显的东西。如果有简单的解决方案,那就太好了(如果这个问题更复杂的话,那就另当别论了)。

当前代码示例:


import numpy
import matplotlib
matplotlib.use("AGG")
import matplotlib.pylab as plt

def makeFrame(srcName, dstName, coloring, sideLength,
              dataRanges, delim, dpi):
    v,V,cmap = coloring
    n = sideLength
    xmin,xmax,ymin,ymax = dataRanges
    A = numpy.empty((n,n),float)
    dx = (xmax-xmin) / (n-1)
    dy = (ymax-ymin) / (n-1)

    srcfile = open(srcName,'rb')
    for line in srcfile:
        lineVals = line[:-1].split(delim)
        x = float(lineVals[0])
        y = float(lineVals[1])
        c = float(lineVals[2])

        #Find index from float value, adjust for rounding
        i = (x-xmin) / dx
        if (i - int(i) ) > .05: i += 1

        j = (y-ymin) / dy
        if (j - int(j) ) > .05: j += 1

        A[i,j] = c
    srcfile.close()
    print "loaded vals"

    fig = plt.figure(1)
    fig.clf()
    ax = fig.gca()
    ScalarMap = ax.pcolorfast(A, vmin = v, vmax = V, cmap = cmap)
    fig.colorbar(ScalarMap)
    ax.axis('image')
    fig.savefig(dstName, dpi = dpi)
    plt.close(1)
    print "saved image"

1 个回答

2

注意事项:

  • 可能还有更好的方法来解决这个内存问题,我并不知道。
  • 我还没能重现这个错误。当我使用 matplotlib.cbook.report_memory() 时,我的内存使用情况似乎正常。

尽管有这些注意事项,我还是想提到一个简单的方法来处理程序不释放内存的问题:使用 multiprocessing 模块,在一个单独的进程中运行出问题的函数。等这个函数结束后,再调用它。每次子进程结束时,你就会重新获得它使用的内存。

所以我建议试试这样的做法:

import matplotlib.cbook as mc
import multiprocessing as mp
import matplotlib.cm as cm

if __name__=='__main__':
    for _ in range(10):
        srcName='test.data'
        dstName='test.png'
        vmin = 0
        vmax = 5
        cmap = cm.jet
        sideLength = 500
        dataRanges = (0.0,1.0,0.0,1.0)
        delim = ','
        dpi = 72
        proc=mp.Process(target=makeFrame,args=(
            srcName,dstName,(vmin,vmax,cmap),sideLength,
            dataRanges,delim,dpi))
        proc.start()
        proc.join()
        usage=mc.report_memory()
        print(usage)

撰写回答