Tiempo de ejecución inconsistente en Python en todos los sistemas

Algo que me estaba volviendo loco con python … solía pensar que solo era Windows , pero estaba equivocado. Puedo tener el mismo código exacto y ejecutarlo varias veces y se ejecuta en cantidades de tiempo muy diferentes. Tome el siguiente código de prueba, por ejemplo:

import math def fib(count): x = 0 while x < count: a = int(((((1 + math.sqrt(5)) / 2) ** x) - (((1 - math.sqrt(5)) / 2) ** (x))) / math.sqrt(5)) x+=1 if __name__ == '__main__': import timeit t = timeit.Timer("fib(1250)", setup="from __main__ import fib",) #print t.timeit(10) count = 10000 results = t.repeat(count, 1) min = 0xFFFF max = 0 sum = 0 for i in results: i = i*1000.0 if i  max: max = i sum+=i print "Min {:.3f} | Max {:.3f} | Max/Min {:.3f} | Avg {:.3f}".format(min, max, max/min, sum/count) 

Básicamente, genera los primeros 1250 elementos de fibonacii 10,000 veces y usa timeit para obtener la cantidad de tiempo que toma cada ejecución. Luego, fusiono esos tiempos y encuentro min, max, promedio y varianza entre min y max (la propagación, por así decirlo).

Aquí están los resultados:

 Windows: Min 3.071 | Max 8.903 | Max/Min 2.899 | Avg 3.228 Mac OS: Min 1.531 | Max 3.167 | Max/Min 2.068 | Avg 1.621 Ubuntu: Min 1.242 | Max 10.090 | Max/Min 8.123 | Avg 1.349 

Entonces, Linux es el más rápido, pero también tiene la mayor variación. Por mucho Pero todos ellos pueden tener un swing bastante salvaje: ¡solo el 200% para Mac, pero el 290% para Windows y el 810% para Linux!

¿Realmente está tomando mucho tiempo diferente para ejecutar? ¿El tiempo no es lo suficientemente preciso? ¿Hay algo más que me esté perdiendo? Estoy trabajando mucho para generar animaciones y necesito el mayor tiempo posible.

Usted está midiendo tiempos muy cortos, y luego incluso un poco de algo que sucede en algún lugar tiene un gran impacto.

Ejecuté su script de prueba en mi máquina (OS X, Core i7, Python 2.7) y realicé este gráfico de results :

introduzca la descripción de la imagen aquí

Puede ver que la mayoría de las veces los resultados de temporización son muy consistentes, pero hay incidentes aislados en que el algoritmo lleva mucho más tiempo (porque está sucediendo algo más).


Hice un pequeño ajuste a su procedimiento de sincronización:

 results=t.repeat(10, 1000) 

Por lo tanto, ahora estamos ejecutando temporizaciones de 1000 llamadas de función. La cantidad total de tiempo es la misma, naturalmente (10000 llamadas):

introduzca la descripción de la imagen aquí

Ahora puedes ver que el rendimiento es mucho más predecible. Puede ser que parte de sus tiempos inestables se deban a la metodología de tiempo, no a tiempos realmente diferentes para llevar a cabo nada. La sincronización de milisegundos es difícil en un entorno de sistema operativo del mundo real. Incluso cuando su computadora “no hace nada”, sigue cambiando tareas, haciendo trabajos en segundo plano, etc.


Entiendo que el punto original no era calcular los números de Fibonacci. Pero si lo fuera, entonces elegir la herramienta correcta hace una diferencia:

 import numpy as np def fib(count): x = np.arange(count) a = (((1 + np.sqrt(5))/2) ** x - ((1 - np.sqrt(5)) / 2) ** x) / np.sqrt(5) a = a.astype('int') 

Esto da:

 Min 0.120 | Max 0.471 | Max/Min 3.928 | Avg 0.125 

Mejora de la velocidad diez veces.


Sobre las imágenes en esta respuesta, están trazadas con matplotlib . El primero se hace así:

 import matplotlib.pyplot as plt # create a figure fig = plt.figure() # create axes into the figure ax = fig.add_subplot(111) # plot the vector results with dots of size 2 (points) and semi-transparent blue color ax.plot(results, '.', c=(0, 0, 1, .5), markersize=2) 

Consulte la documentación de matplotlib . Es más fácil comenzar utilizando IPython y pylab .

Hice una ttwig similar a @drV (¡dale el voto, él fue el primero!), La diferencia es que ordené los resultados para que pudieras ver una línea de tendencia. La sugerencia es que, aunque el máximo es alto, el promedio es bajo, por lo que hay algunos valores atípicos al final.

introduzca la descripción de la imagen aquí

Usé pylab simplemente agregando esto al fondo:

 from pylab import * results.sort() plot(range(len(results)),results) show()