我已经在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(),而mc.collect()所做的就我所知,即使调用了python,malloc()分配的内存也不会返回给系统。使用它自己的malloc(PyObject_malloc()和PyObject_Free()),但它们具有相同的行为,请看这里:stackoverflow.com/questions/2215259/
@singularity-我愿意尝试使用tcmalloc的说明来强制它释放对象,以查看其是否有效。您知道如何强制它使用该库。是否必须以特殊方式编译Python并将其链接到我假设的那个库?
@J Spen:看这里:pushtheweb.com/2010/06/python-and-tcmalloc,也许可以为您提供更多详细信息。
@singularity-我知道该链接,但是不确定如何使用TCMalloc为收集器编译Python,但是我已在此处张贴文章以查看它们是否会响应。
旁注,实际上不需要手动删除函数,类和代码中的局部变量。 python GC非常聪明,可以在不需要此变量时实现,并会自行对其进行排序。
IPython甚至在%reset之后都可以保留引用,除非您运行的开发版本应该在该版本中对其进行修复。看到这里:github.com/ipython/ipython/issues/141
@Jakob-我知道通常不需要del,但是我在调??试过程中添加了它们,因为我正在查看是否由于某种原因使引用保持完整并释放了内存。没有作用。
@Thomas K-有趣的笔记,但是使用%run时要阅读这些笔记。在Matplotlib完全支持Ipython 0.11的新功能之前,我不会运行开发版本,据我所知,该功能仍不完全兼容。另外,在普通的python shell中也会发生上述相同的问题。
@J Spen:我只是想提及一下,以防万一它使测试变得更加混乱。也可以保留没有%run的引用,但是由%run创建的引用最难追踪。
@J Spen-无论其价值如何,这似乎都不会泄漏我的机器上的内存(Python 2.7,numpy 1.6,OpenSuse 11.4,内核2.6.37.6)。
虚拟内存不是稀缺资源。 由于每个进程都有自己的地址空间,因此无需将其返回给系统。 你的实际问题是什么? 此行为导致您什么问题?
移动设备和开发板通常没有虚拟内存。 他们有RAM,通常就是这样。
@jww这是完全不真实的,甚至十年前都不是真实的。 您可能会发现没有虚拟内存的处理器作为诸如太阳能系统之类的电源控制器,也许还有一些很小的开发板(如arduino)。 就是这样。 我十年来没有见过没有虚拟内存的移动设备。
我的坏大卫。 它们具有虚拟内存,每个进程通常都有其自己的空间,但是它们没有交换文件。 您不能将这些设备当作台式机或服务器使用。 如果这样做,则会遇到很多内存不足的情况。 我似乎还记得在某些只有256 MB内存的早期iPad上,malloc的最大大小是32 MB或64 MB。
我安装了最新的numpy svn,问题消失了。 我假设它在numpy函数之一内部。 我从来没有机会进一步研究它。