2011-08-19 10 views
9

Estoy ejecutando una aplicación django que incluye matplotlib y permite al usuario especificar los ejes del gráfico. Esto puede dar como resultado 'Error de desbordamiento: se excedió la complejidad de Agg'Los errores Matplotlib provocan una pérdida de memoria. ¿Cómo puedo liberar esa memoria?

Cuando eso sucede, hasta 100MB de RAM quedan atados. Normalmente, libero esa memoria utilizando fig.gcf(), plot.close() y gc.collect(), pero la memoria asociada con el error no parece estar asociada con el objeto de trazado.

¿Alguien sabe cómo puedo liberar esa memoria?

Gracias.

Aquí hay un código que me da el error de complejidad Agg.

import matplotlib 
matplotlib.use('Agg') 
import matplotlib.pyplot as plt 
import numpy as np  
import gc 

a = np.arange(1000000) 
b = np.random.randn(1000000) 

fig = plt.figure(num=1, dpi=100, facecolor='w', edgecolor='w') 
fig.set_size_inches(10,7) 
ax = fig.add_subplot(111) 
ax.plot(a, b) 

fig.savefig('yourdesktop/random.png') # code gives me an error here 

fig.clf() # normally I use these lines to release the memory 
plt.close() 
del a, b 
gc.collect() 

Respuesta

9

Supongo que puede ejecutar el código que publicó al menos una vez. El problema solo se manifiesta después de ejecutar el código publicado muchas veces. ¿Correcto?

Si es así, lo siguiente evita el problema sin identificar realmente el origen del problema. Quizás eso sea algo malo, pero esto funciona en un momento: simplemente use multiprocessing para ejecutar el código de memoria intensiva en un proceso separado. No tiene que preocuparse por fig.clf() o plt.close() o del a,b o gc.collect(). Toda la memoria se libera cuando el proceso finaliza.

import matplotlib 
matplotlib.use('Agg') 
import matplotlib.pyplot as plt 
import numpy as np  

import multiprocessing as mp 

def worker(): 
    N=1000000 
    a = np.arange(N) 
    b = np.random.randn(N) 

    fig = plt.figure(num=1, dpi=100, facecolor='w', edgecolor='w') 
    fig.set_size_inches(10,7) 
    ax = fig.add_subplot(111) 
    ax.plot(a, b) 

    fig.savefig('/tmp/random.png') # code gives me an error here 

if __name__=='__main__': 
    proc=mp.Process(target=worker) 
    proc.daemon=True 
    proc.start() 
    proc.join() 

Usted no tiene que proc.join() tampoco. El join bloqueará el proceso principal hasta que se complete el worker. Si omite el join, entonces el proceso principal simplemente continúa con el proceso worker trabajando en segundo plano.

+0

El código que he publicado falla la primera vez a través. Fue creado para recrear el caso especial de un usuario que acerca demasiado el eje y para datos de alta frecuencia de muestreo. Si un diagrama parece un lavado de azul sin mostrar ningún fondo blanco, el código falla. Sin embargo, su solución parece una mejor forma de administrar la memoria. Soy un novato y no entiendo completamente qué está pasando con el bloque 'if __name__ == '__main __':'. Intentaré agregar esto a mi código. ¿Puede indicarme un recurso que explique lo que está sucediendo? O puedes ofrecer una explicación rápida. Gracias. – sequoia

+0

@sequoia: En ese caso, tal vez deba restringir al usuario, por lo que en ningún caso el usuario puede solicitar que se graben 1e6 puntos. El bloque 'if __name __...' no es necesario a menos que esté en Windows. Me encantaría tratar de explicar cualquier pregunta específica que tenga, pero creo que en este caso todo se explica mucho mejor de lo que puedo [aquí] (http://docs.python.org/library/multiprocessing.html#the -process-class) – unutbu

+0

Gracias, ese es un enlace útil. Voy a usar tu implementación. Y tome su sugerencia para limitar el alcance de las solicitudes de los usuarios. – sequoia