Python 内存问题
我开始学习用Python编程,但我有点记忆方面的问题(抱歉我的英语不好)。
我在我的算法中写了一个循环,但每次循环的时候,程序消耗了很多内存。我有3GB的内存,AMD 64 x2处理器,操作系统是64位的Windows 7。
每次循环大约消耗800MB的内存,我觉得这太多了。以下是我代码的一部分:
from sympy import Symbol, diff, flatten
import numpy as np
from numpy import linalg
from math import log, sqrt, cos, pi
import matplotlib.pyplot as plt
L = 7 #numero de variables
X = [Symbol('x%d' % i) for i in range(L*(L+1))] #Las variables simbolicas
XX = [X[i] for i in xrange(L)]
LAM = []
# Parametros
Pr = 10
Eps = 0
Ome = 5
LL = 0.5
b = 2
Gam = 0.2*2*(pi**2)
ran1 = xrange(L)
ran2 = xrange(L*L)
ran3 = xrange(0,L*(L-1)+1,L)
ran4 = xrange(L,2*L,1)
dt = 0.01
TMAX = 60
def f(x,R,Tau):
return [Pr*((1 + Eps*cos(Ome*Tau))*x[2] - LL*x[0] - (1 -LL*x[5])) , \
Pr*((1 + Eps*cos(Ome*Tau))*x[3] - LL*x[1] - (1 - LL)*x[6]),\
R*x[0] - x[2] - x[0]*x[4],R*x[1] - x[3] - x[1]*x[4],(x[0]*x[2] + x[1]*x[3])/2 - b*x[4],\
(1/Gam)*(x[0] - x[5]),(1/Gam)*(x[1] - x[6])]
def Jacobian(f,x): #num son los numeros en el que se evalua la matriz jacobiana, x las variables y f la funcion
return [[diff(f[i],x[n]) for i in ran1] for n in ran1]
def Y(x):
return[[x[i+j] for j in ran3] for i in ran4]
#Ahora la multiplicacion de Y traspuesto por Jacobian traspuesto
def JY(r,Tau):
J = flatten((np.dot(np.array(Jacobian(f(XX,r,Tau),XX)),np.array(Y(X)))).T)
return [J[i] for i in ran2]
def Func(x,r,Tau): #Expandemos las funciones en un solo arreglo
FFF = []
map(lambda g: FFF.append(g),f(XX,r,Tau))
map(lambda g: FFF.append(g),JY(r,Tau))
return map(lambda f: f.evalf(subs={X[j]:x[j] for j in xrange(L*(L+1))}),FFF)
def RKutta(xi,r):
i = 1
while i <= int(TMAX/dt):
Tau = 0
YY = xi
k1 = np.array(Func(YY,r,Tau))*dt
k2 = (np.array(Func(YY + k1/2,r,Tau/2)))*dt
k3 = (np.array(Func(YY + k2/2,r,Tau/2)))*dt
k4 = (np.array(Func(YY + k3,r,Tau)))*dt
xi = YY + (k1/6) + (k2/3) + (k3/3) + (k4/6)
Tau = Tau + dt
i = i + 1
return [xi[j] for j in xrange(len(xi))]
def lyap(xxi):
u = [i for i in flatten(np.random.rand(1,L))]
PhiT = (np.array([[float(xxi[i+j]) for j in ran3] for i in ran4])).T
PU = np.dot(PhiT,u)
summ = 0
jj = 0
while jj < len(PU):
summ += (float(PU[jj]))**2
jj = jj + 1
lam = log(sqrt(summ))/TMAX
return lam
R = 46.5
Rmax = 48.5
Rstep = 0.5
while R <= Rmax:
xi = [5,5,5,5,5,5,5] #Condiciones Iniciales
for i in ran2:
xi.append(None)
for i in ran4:
for j in ran3:
if (i+j+1)%(L+1) == 0:
xi[i+j] = 1
else:
xi[i+j] = 0
#Ahora el Runge Kutta para integrar todo el sistema
#Y.append([r for r in xx])
# savetxt('butterfly.txt', Y, fmt="%12.6G")
#print Y
XI = RKutta(xi,R)
lamb = lyap(XI)
LAM.append([R,lamb])
print [R,lamb]
R = R + Rstep
#print LAM
#x = [LAM[i][0] for i in xrange(len(LAM))]
#y = [LAM[i][1] for i in xrange(len(LAM))]
np.savetxt('lyap3.txt', LAM, fmt="%12.6G")
#plt.axis([10,30,-3,3]);
#plt.scatter(x,y)
#plt.show()
我不知道问题出在哪里。可能是在Runge Kutta步骤上,或者是架构方面的问题。每一步似乎都没有释放内存,而我并没有存储任何东西,只是在代码的最后保存了一对数字。
希望我表达得清楚。
#
好的,我编辑了这个帖子并发布了完整的代码,希望有人能帮忙 :)。我改了很多东西,但仍然有内存问题。每次循环大约使用600MB的内存。
#
提前谢谢大家。
3 个回答
看起来你在创建非常大的列表。可以看看能不能用迭代器来替代一些列表推导式。
什么是L?很多代码使用O(L^2)的存储空间,所以如果L很大,那就会占用很多内存。
没有上下文的话,跟着代码走有点难,因为你在多个地方用了numpy(有的地方是用np前缀,有的地方没有),而evalf可能是来自sympy……但我们看不到你导入的库。
我猜测,你的一些列表推导式可能会生成临时列表,这些列表存在的时间比你预期的要长。你可以考虑把它们改成生成器。还有一种方法是尽量多用map()或者类似的函数。
我还注意到你在不需要的地方用了不太符合Python习惯的索引迭代。函数首先创建了一个叫FFF的列表,一个一个地添加元素(这比较耗费资源),然后又通过索引来遍历这个列表,实际上没有必要。你可以用 [f(item) for item in seq]
来代替 [f(seq[i]) for i in xrange(len(seq))]
,或者更好的是,直接用 map(f, seq)
,在这种情况下,尽量不要创建临时列表。