Python 内存问题

1 投票
3 回答
1593 浏览
提问于 2025-04-16 06:38

我开始学习用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 个回答

0

看起来你在创建非常大的列表。可以看看能不能用迭代器来替代一些列表推导式。

0

什么是L?很多代码使用O(L^2)的存储空间,所以如果L很大,那就会占用很多内存。

1

没有上下文的话,跟着代码走有点难,因为你在多个地方用了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),在这种情况下,尽量不要创建临时列表。

撰写回答