2010-07-22 20 views
10

He estado corriendo scripts de Python que hacen varias llamadas a algunas funciones, digo F1 (x) y F2 (x), que se ven un poco como esto:Memoria estática en python: ¿los bucles crean nuevas instancias de variables en la memoria?

x = LoadData() 

for j in range(N): 
    y = F1(x[j]) 
    z[j] = F2(y) 

    del y 

SaveData(z) 

El rendimiento es mucho más rápido si sigo la línea "del y" Pero no entiendo por qué esto es verdad. Si no uso "del y", entonces rápidamente me quedo sin RAM y tengo que recurrir a la memoria virtual, y todo se ralentiza. Compre si uso "del y", entonces estoy enjuagando repetidamente y reasignando la memoria para y. Lo que me gustaría hacer es sentarme como memoria estática y reutilizar la memoria en cada llamada F1 (x). Pero por lo que puedo decir, eso no es lo que está sucediendo.

Además, no estoy seguro de si es relevante, pero mis datos consisten en matrices numpy.

+0

Esta pregunta probablemente asuma que y se declaró primero dentro del ciclo, debería haber mencionado esto. ¡Sin embargo, no dude en comentar este aspecto de la pregunta! –

+3

Si no te gusta el 'del y' explícito, extrae el cuerpo del bucle en una función. De esta forma, cualquier variable que se encuentre dentro del ciclo se limpiará automáticamente para cada iteración. – Duncan

Respuesta

11

Sin el del y es posible que necesite el doble de memoria. Esto se debe a que para cada pasada a través del ciclo, y está vinculado al valor anterior de F1 mientras se calcula el siguiente.

una vez F1 devuelve y se recupera a ese nuevo valor y se puede liberar el resultado antiguo F1.

Esto significaría que el objeto devuelto por F1 ocupa mucho de la memoria

y habiendo abierto el bucle para el primer par de iteraciones se vería así

y = F1(x[0]) # F1(x[0]) is calculated, then y is bound to it 
z[j] = F2(y) 
y = F1(x[1]) # y is still bound to F1(x[0]) while F1(x[1]) is computed 
       # The memory for F1(X[0]) is finally freed when y is rebound 
z[j] = F2(y) 

usando del y es una buena solución si esto es lo que está sucediendo en tu caso.

+0

escuchar escuchar - esto explica por qué tiene un mejor rendimiento con 'del y' –

+1

Gracias, esto debe ser exactamente lo que está sucediendo: Sin el del, mi uso de memoria se duplica, se derrama un poco en la memoria virtual (ya que mi memoria RAM se encuentran entre una y dos instancias de y) y los slogs de scripts están en bajo rendimiento. Me quedaré con la solución por ahora; Gracias de nuevo por explicar cuándo/cómo se crean las instancias de y. –

0

Para valores muy grandes de N use xrange en lugar de range para guardar la memoria. También puede anidar funciones pero no sé si esto lo ayudará. : \

x = LoadData() 

for j in xrange(N): 
    z[j] = F2(F1(x[j])) 

SaveData(z) 

Tal F1 y F2 están haciendo copias innecesarias de objetos, la mejor manera sería en el lugar, algo así como:

x = LoadData() 
for item in x: 
    item.F1() 
    item.F2() 
SaveData(x) 

Lo siento si puede responder no es útil

+0

Me preocupaba que mi ejemplo permitiera anidar; no es una opción tan práctica en el guión real.Creo que los comentarios de gnibbler describen correctamente la situación, pero gracias por sus comentarios. No estaba familiarizado con la función xrange hasta que la señaló. –

1

lo que realmente quiere es algo que es raro de hacer en python; desea asignar una región de memoria para y y pasar el puntero a esa región a F1() para que pueda usar esa región para generar el siguiente valor de y. esto evita en F1() haga su asignación propia para el nuevo valor de y, la referencia a la que se escribe a continuación en su propia variable y (que en realidad no es el valor de lo F1() calculada sino una referencia a ella)

Ya hay una pregunta ASÍ sobre pasar por referencia en python: How do I pass a variable by reference?

Cuestiones relacionadas