python import gc_即使在gc.collect()之后,分配给Python的内存也不会在Linux中释放回来...

本文探讨了一个Python程序中出现的内存泄露问题,特别是在使用numpy和scipy库时。通过实验发现,即使不再使用的内存也无法通过垃圾回收机制释放,该问题在不同操作系统上表现一致。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我已经在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函数之一内部。 我从来没有机会进一步研究它。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值