Foros del Web » Programando para Internet » Python »

Apuntes sobre calculo de rendimiento.

Estas en el tema de Apuntes sobre calculo de rendimiento. en el foro de Python en Foros del Web. En algunos casos nos puede interesar saber el tiempo que tarda en ejecutarse un programa o función y el consum de memoria que ocupa. Tenemos ...
  #1 (permalink)  
Antiguo 30/04/2014, 03:09
 
Fecha de Ingreso: febrero-2011
Mensajes: 54
Antigüedad: 9 años, 3 meses
Puntos: 18
Apuntes sobre calculo de rendimiento.

En algunos casos nos puede interesar saber el tiempo que tarda en ejecutarse un programa o función y el consum de memoria que ocupa.

Tenemos por ejemplo la función:

Código Python:
Ver original
  1. def fibonacci(n):
  2.     if n < 3: return 1
  3.     else:
  4.         return fibonacci(n-2) + fibonacci(n-1)

Que calcula el número de fibonacci.

Para controlar el tiempo de ejecución bastaria con importar el módulo time y hacer un registro antes y otro después de su ejecución y calcular la diferencia.

Código Python:
Ver original
  1. import time
  2.  
  3. def func_time():
  4.     ti = time.time()
  5.     fibonacci(20)
  6.     tf = time.time()
  7.     print tf-ti
  8.    
  9. func_time()

Código:
0.00212001800537
Para hacer esto más práctico podemos hacer un decorador.
Un decorador es una función que recibe como parámetro otra función y devuelve el resultado de ésta modificado( decorado).

Código Python:
Ver original
  1. def timeit(func):
  2.     def timed(*args, **kw):
  3.         ti = time.time()
  4.         result = func(*args, **kw)
  5.         tf = time.time()
  6.         print('Time:{:.10f} sec'.format(tf-ti))
  7.         return result
  8.     return timed

Y lo aplicamos de esta forma:

Código Python:
Ver original
  1. @timeit
  2. def prueba():
  3.     return fibonacci(10)
  4. print prueba()

o bien:

Código Python:
Ver original
  1. @timeit
  2. def main(n):
  3.     def fibonacci(n):
  4.         if n < 3: return 1
  5.         else:
  6.             return fibonacci(n-2) + fibonacci(n-1)
  7.    
  8. print main(20)

En este caso al ser una función recursiva no podemos aplicar el decorador directamente a la función ya que nos daría un resultado para cada recursión. En caso de que no lo sea, sí podemos hacerlo.

Código Python:
Ver original
  1. @timeit
  2. def cuadrado(n):
  3.     return n**2
  4.  
  5. print cuadrado(20)

Código:
Time:0.0000021458 sec
400

Añadimos algunas cosas más: El proceso PID y el consumo de RAM con el módulo resource.
Código Python:
Ver original
  1. import resource
  2. import time
  3. import os
  4.  
  5. def timeit(func):
  6.     def timed(*args, **kw):
  7.         ts = time.time()
  8.         pid = os.getppid()
  9.         result = func(*args, **kw)
  10.         te = time.time()
  11.         maxmem = (resource.getrusage(resource.RUSAGE_SELF).ru_maxrss)/1000
  12.         info = (pid, func.__name__, te-ts, maxmem)
  13.         print('PID:{}\nName:{}\nTime:{:.10f} sec\nRAM:{} MB'.format(*info))
  14.         return result
  15.     return timed

Si guardamos este archivo como por ejemplo decotime.py en el path correspondiente. Podemos importarlo desde nuetros programas

Código Python:
Ver original
  1. import decotime
  2.  
  3. @decotime.timeit
  4. def prueba():
  5.     return fibonacci(35)
  6. print prueba()

Con lo que, sobre la misma función anterior para fibonacci(35) obtengo:

Código:
PID:8833
Name:prueba
Time:2.8051321507 sec
RAM:92 MB
9227465
fibonacci(40)

Código:
PID:8833
Name:prueba
Time:31.0330379009 sec
RAM:89 MB
102334155
Y una versión con memoización de fibonacci:
Código Python:
Ver original
  1. import decotime
  2.  
  3. @decotime.timeit
  4. def main(n):
  5.  
  6.     mem = {1:1,2:1}
  7.     def fibo(n):
  8.         if n < 3: return 1
  9.         if not n in mem:
  10.             mem[n] = fibo(n-1) + fibo(n-2)
  11.         return mem[n]
  12.    
  13. main(40)

Código:
PID:8833
Name:prueba
Time:0.0000319481 sec
RAM:96 MB
102334155
La diferencia es espectacular...

Saludos.

Pd, no he encontrado en la documentación de resource nada sobre las unidades que devuelve ru_maxrss asi que no sé si esto es cierto :
maxmem = (resource.getrusage(resource.RUSAGE_SELF).ru_maxrs s)/1000
- Es posible que algunas cosas solo funcionen en *nix.

Etiquetas: calculo, programa
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta

SíEste tema le ha gustado a 1 personas




La zona horaria es GMT -6. Ahora son las 16:42.