【问题标题】:Memory allocated to Python is not released back in Linux even after gc.collect()即使在 gc.collect() 之后,分配给 Python 的内存也不会在 Linux 中释放回
【发布时间】:2011-05-12 08:21:24
【问题描述】:

我在 Python 中编写的代码不会按应有的方式释放内存。内存被 Python 占用,但即使不再使用,也不会被释放。即使您使用 ctrl+c 中断正在运行的程序。删除变量并运行 gc.collect() 它似乎没有收集。或者与 Ipython 中的相同并运行 %reset。内存不会被释放并且运行 gc.collect() 没有效果。我在 Windows 中对此进行了测试,因为我想看看它是否可能与垃圾收集器库一起使用。看来情况确实如此。在 Linux 中运行以下代码,然后在 Windows 中运行。然后比较内存使用情况。您将需要安装 numpy 和 scipy。对此问题的任何帮助或见解将不胜感激。

导入模型,创建实例,然后运行 ​​createSpecific()。

这是在 Ubuntu 10.04 中展示此行为的代码:

from numpy import array, maximum,intersect1d, meshgrid, std, log, log10, zeros, ones, argwhere, abs, arange, size, copy, sqrt, sin, cos, pi, vstack, hstack, zeros, exp, max, mean, savetxt, loadtxt,  minimum,  linspace,  where
from numpy.fft import fft
from scipy.stats import f_oneway, kruskal, sem, scoreatpercentile
#import matplotlib
#matplotlib.use('cairo.pdf')
from matplotlib.pyplot import plot, clf, show, cla, xlim, xscale, imshow, ylabel, xlabel, figure, savefig, close,  bar,  title,  xticks, yticks, axes, axis
from matplotlib.axes import Axes
from mpl_toolkits.mplot3d import Axes3D
#from enthought.mayavi import mlab
from matplotlib import cm
import matplotlib.pyplot as plt
import os
from time import clock
from timeit import Timer
class Model:

#Constructors and default includes
    def __init__(self, prevAud = None,  debug=False):

        if (prevAud == None):
            self.fs=16000. #sample rate
            self.lowFreq=60. 
            self.hiFreq=5000.     
            self.numFilt=300 #number of channel
            self.EarQ = 9.26449   #9.26449
            self.minBW = 24.7     #24.7
            self.integrationWindow=.01
            self.sliceAt=.035
            self.maxOverallInhibit = 0.1
            self.winLen = int(self.fs*self.integrationWindow+.01) #default integration window 10 ms
            self.fullWind = 0.300
            self.outShortWindow = None
            self.siderArray = None
            self.maxNormalizeValue = .284     # Optimized at .284
            self.outputSemiModel = None
            self.semitones = 11
            self.activationTrace = None
        return




    def setErbScale(self, erbScale = None):
        if (erbScale ==None):
            self.erbScale = arange(100,500,5)
        else:
            self.erbScale = erbScale        

    def trainModel(self,soundVec=None, fs=None, lowfreq=None, highfreq=None, numfilt=None, figto=0, savefig = 'N', prompts=False, plotter=False):
        self.setErbScale()
        templateArray = self.intWindow(self.halfWaveRec(self.creGammatone(soundVec))) 
        for i in xrange(templateArray[0].size):        
            self.outerTest(self.innerTest(templateArray[:,i]))

        return templateArray   


    def createSpecific(self, freqArray = None, semitones = 11, timeforHarm = .3, soundVec=None, fs=None, lowfreq=None, highfreq=None, numfilt=None, figto=0, saveData='N', fileDir='TempRunT/', prompts=False, plotter=False):
        if (freqArray == None):
            self.setErbScale()
            freqArray = self.erbScale
        if (type(semitones) == int):
            semitones = arange(semitones+1)
        totalRuns = int(timeforHarm/self.integrationWindow+.001)
        inhibitWindowArray = zeros((freqArray.size,(semitones.size),self.numFilt,totalRuns))
        for x in xrange(freqArray.size):
            tempHarm = self.makeHarmonicAmpMod(freqArray[x],timeforHarm, numHarm=7,modulation=10)
            for y in semitones:
                tempChord = self.makeSemiChordAmpMod(tempHarm, freqArray[x],timeforHarm,modulation=10,numHarm=7,semi=y)
                inhibitWindowArray[x,y] = self.trainModel( tempChord, savefig = 'N', plotter=plotter)


        self.inhibitWindowArray = inhibitWindowArray

    def creGammatone(self, soundVec):

        temp = zeros((300,soundVec.size))
        for i in xrange(temp[:,0].size):
            temp[i] = -1**i*soundVec
        return temp

    def halfWaveRec(self, halfWaveFilts):

        filtShape = halfWaveFilts.shape
        if (filtShape[1] != int(self.fs*self.fullWind)):
            halfWaveFilts = hstack((halfWaveFilts,zeros((self.numFilt,int(self.fs*self.fullWind)-filtShape[1]))))
        temp = zeros((halfWaveFilts[:,0].size,halfWaveFilts[0].size))
        halfWaveFilts = maximum(halfWaveFilts,temp)

        del temp                
        return halfWaveFilts

    def intWindow(self, integratedFilts):
        winlen = self.winLen

        length = integratedFilts[0].size/winlen
        mod = integratedFilts[0].size%winlen
        outShortWindow = zeros((integratedFilts[:,0].size,length))
        meanval = 0

        if (mod != 0):
            for i in xrange(integratedFilts[:,0].size):
                mean(integratedFilts[i,0:-mod].reshape(length,winlen),1,out=outShortWindow[i])
        else:
            for i in xrange(integratedFilts[:,0].size):
                mean(integratedFilts[i].reshape(length,winlen),1,out=outShortWindow[i])
        del integratedFilts
        return outShortWindow    

    def innerTest(self, window):
        temper = copy(window)
        sider = 7
        st = .04
        sizer = temper.size
        inhibVal = 0
        for j in xrange(sider):
            inhibVal = (temper[0:j+sider+1].sum())*(sider*2+1)/(sider+1+j)
            window[j] += - st*(inhibVal)
        for j in xrange(sider,sizer - sider):
            inhibVal = temper[j-sider:j+sider+1].sum()
            window[j] += - st*(inhibVal)
        for j in xrange(sizer-sider, sizer):
            inhibVal = (temper[j-sider:sizer].sum())*(sider*2+1)/(sider+sizer-j)
            window[j] += - st*(inhibVal)

        maxsub = max(window) * self.maxOverallInhibit
        window += - maxsub    
        del temper
        return window

    def outerTest(self, window):
        newSatValue = scoreatpercentile(window, (76))
        numones = where(window > newSatValue)
        window[numones]=1
        self.maxSatValue = newSatValue
        del numones
        return window

    def makeHarmonicAmpMod(self, freq = 100, time = 1.,modulation=10, fsamp=None, numHarm=7):
        if fsamp == None: fsamp = self.fs
        samples = arange(time*fsamp)
        signal = 0
        for x in xrange(1,(numHarm+1),1):
            signal = signal + sin(samples/float(fsamp)*x*freq*2*pi)
        signal = (signal)*maximum(zeros(time*fsamp),sin((samples/float(fsamp)*modulation*2*pi)))
        return signal

    def makeSemiChordAmpMod(self, harmVec = None, freq=100, time = 1.,  modulation=10, fsamp=None, numHarm=7, semi = 2):
        if (harmVec == None): harmVec = self.makeHarmonicAmpMod(freq,time,modulation,fsamp,numHarm)
        if (semi == 0): return harmVec
        return harmVec + self.makeHarmonicAmpMod(freq*(2**(semi/12.)),time,modulation,fsamp,numHarm)

【问题讨论】:

  • python 分配的内存在后台使用 malloc(),而 malloc() 分配的内存在调用 free() 后不会返回系统,这与 gc.collect() 的作用相同据我所知,即使 python 使用它自己的 malloc(PyObject_malloc() 和 PyObject_Free()),但它们具有相同的行为,请看这里:stackoverflow.com/questions/2215259/…
  • @singularity - 我愿意尝试使用 tcmalloc 的说明来强制它释放对象,看看它是否有效。你知道如何强制它使用那个库。 Python 是否必须以特殊方式编译并链接到我假设的那个库?
  • @J Spen:看这里:pushingtheweb.com/2010/06/python-and-tcmalloc 也许这可以给你更多的细节。
  • @singularity - 我知道那个链接,但我不确定如何使用 TCMalloc 为收集器编译 Python,但我已经在那里发布,看看他们是否会回复。
  • 旁注,确实不需要手动删除函数、类和代码中的局部变量。 python GC 足够聪明,可以意识到什么时候不需要这个变量,并会自行对其进行排序。

标签: python memory-management garbage-collection numpy malloc


【解决方案1】:

虚拟内存不是稀缺资源。由于每个进程都有自己的地址空间,因此无需将其返回给系统。你的实际问题是什么?这种行为会给您带来什么问题?

【讨论】:

  • 移动设备和开发板通常没有虚拟内存。他们有 RAM,通常就是这样。
  • @jww 这完全不真实,十年前甚至都不是真的。您可能会在太阳能系统和一些非常小的开发板(如 arduino)中找到没有虚拟内存的处理器作为电源控制器。但仅此而已。十年来我还没有见过没有虚拟内存的移动设备。
  • 我的坏大卫。它们有虚拟内存,每个进程通常都有自己的空间,但它们没有交换文件。您不能将这些设备视为台式机或服务器。如果你这样做了,那么你会经历很多内存不足的杀戮。我似乎记得在一些只有 256 MB 内存的早期 iPad 上,malloc 的最大大小是 32 MB 或 64 MB。
【解决方案2】:

我已经安装了最新的 svn 的 numpy 并且问题已经消失了。我认为它在其中一个 numpy 函数中。我从来没有机会深入研究它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-19
    • 1970-01-01
    • 2016-11-05
    • 2012-06-12
    相关资源
    最近更新 更多