20 votos

Perfil de Asignación de Memoria en Python (con soporte para arrays de Numpy)

Tengo un programa que contiene un gran número de objetos, muchos de ellos de los arrays de Numpy. Mi programa es el intercambio miserablemente, y estoy tratando de reducir el uso de memoria, ya que en realidad no puede finis en mi sistema con los requisitos de memoria actuales.

Estoy en busca de un buen analizador que me permitiría comprobar la cantidad de memoria consumida por los distintos objetos (me estoy imaginando una memoria contraparte cProfile) por lo que yo sé dónde hay que optimizar.

He oído cosas decentes sobre Heapy, pero Heapy lamentablemente no soporta arrays de Numpy, y la mayor parte de mi programa consiste en arrays de Numpy.

9voto

Fabian Pedregosa Puntos 1611

Una forma de abordar el problema si está llamando a un montón de diferentes funciones y no está seguro de donde el intercambio proviene sería el uso de la nueva funcionalidad de trazado de memory_profiler. En primer lugar usted debe decorar las diferentes funciones que se usan con @perfil. Para simplificar, voy a utilizar el ejemplo examples/numpy_example.py se entregan con memory_profiler que contiene dos funciones: create_data() y process_data()

Para ejecutar la secuencia de comandos, en lugar de correr con el intérprete de Python, se utiliza la mprof ejecutable, que es

$ mprof run examples/numpy_example.py

Esto creará un archivo llamado mprofile_??????????.dat, donde el ? contendrá los números que representa la fecha actual. Para graficar el resultado, simplemente escriba mprof plot y generará una trama similar a este (si tiene varios .archivos dat se tomará siempre el último):

output of memory_profiler's mprof

Aquí puedes ver el consumo de memoria, con corchetes, indicando al entrar/salir de la función actual. De esta manera es fácil ver que la función process_data() tiene un pico el consumo de memoria. A más de profundizar en su función, puede utilizar la línea-por-línea del analizador para ver el consumo de memoria de cada línea en su función. Este se ejecuta con

python -m memory_profiler examples/nump_example.py

Esto le puede dar una salida similar a esta:

Line #    Mem usage    Increment   Line Contents
================================================
    13                             @profile
    14  223.414 MiB    0.000 MiB   def process_data(data):
    15  414.531 MiB  191.117 MiB       data = np.concatenate(data)
    16  614.621 MiB  200.090 MiB       detrended = scipy.signal.detrend(data, axis=0)
    17  614.621 MiB    0.000 MiB       return detrended

donde es claro que scipy.de la señal.detrend está asignando una gran cantidad de memoria.

8voto

bmu Puntos 7109

Eche un vistazo a la memoria del analizador. Ofrece línea por línea y perfiles Ipython de integración, lo que hace que sea muy fácil de utilizar:

In [1]: import numpy as np

In [2]: %memit np.zeros(1e7)
maximum of 3: 70.847656 MB per loop

Actualización

Como se ha mencionado por @WickedGrey no parece ser un error (ver github issue tracker) cuando se llama a una función más de una vez, que puedo reproducir:

In [2]: for i in range(10):
   ...:     %memit np.zeros(1e7)
   ...:     
maximum of 1: 70.894531 MB per loop
maximum of 1: 70.894531 MB per loop
maximum of 1: 70.894531 MB per loop
maximum of 1: 70.894531 MB per loop
maximum of 1: 70.894531 MB per loop
maximum of 1: 70.894531 MB per loop
maximum of 1: 70.902344 MB per loop
maximum of 1: 70.902344 MB per loop
maximum of 1: 70.902344 MB per loop
maximum of 1: 70.902344 MB per loop

Sin embargo, no sé hasta qué punto los resultados tal vez influenciado (que parece ser no tanto en mi ejemplo, por lo que dependiendo de su caso de uso es tal vez útil) y cuando este problema tal vez fijo. Me pidió que en github.

0voto

Gyppo Puntos 355

Usted puede simplemente guardar/pickle algunos de los arrays de disco en archivos tmp cuando no se utilizan? Eso es lo que he tenido que hacer en el pasado con matrices grandes. Por supuesto, esto va lento el programa, pero al menos lo voy a terminar. A menos que usted necesita todos a la vez?

0voto

Bastian Venthur Puntos 294

He intentado valgrind con la massif herramienta?

valgrind --tool=massif python yourscript.py

se creará un archivo llamado massif.out.xxx que usted puede inspeccionar a través de

ms_print massif.out.xxx | less

cuenta con todo tipo de información útil, pero la trama de la derecha en el comienzo debe ser lo que usted está buscando. También echa un vistazo macizo tutorial en el valgrind página de inicio.

El uso de valgrind está muy avanzada y podría haber maneras más fáciles de hacer de lo que usted está buscando.

0voto

neo Puntos 586

Desde numpy 1.7 existe un semi construido en la forma de hacer un seguimiento de las asignaciones de memoria:

https://github.com/numpy/numpy/tree/master/tools/allocation_tracking

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by: