2012-04-28 38 views
37

El comando de magia IPython% timeit hace bien su trabajo para medir el tiempo requerido para ejecutar algún código de Python. Ahora, quiero usar algo análogo en la secuencia de comandos de Python. Sé sobre el módulo de tiempo, sin embargo, tiene varias desventajas, por ejemplo, ¿cómo seleccionar el número de carreras de forma adaptativa? es decir, el código predeterminadoCómo ejecutar una magia de IPython desde una secuencia de comandos (o cronometrar una secuencia de comandos de Python)

import timeit 
t=timeit.Timer("code(f)", "from __main__ import code,f") 
t.timeit() 

ejecuta el código millones de veces. El comando% timeit IPyhton magic lo hace automáticamente. Sugiero que podría usar algo como el código MATLAB http://www.mathworks.com/matlabcentral/fileexchange/18798

que hace todo el trabajo automáticamente (y también dice si la sobrecarga de la función es grande).

¿Cómo puedo llamar a% timeit magic desde un script de Python (o tal vez hay una mejor solución de tiempo)?

+7

Si lo convierte en un script de IPython (* .ipy), entonces toda la sintaxis de IPython estará disponible, y puede hacer '% timeit foo' como lo haría normalmente. – minrk

+1

Gracias, es una buena sugerencia. Pero utilizo esto en un archivo de modo orgánico, y creo que solo conoce Python :) –

Respuesta

44

Depende un poco de la versión de IPython que tenga. Si tiene 1.x:

from IPython import get_ipython 
ipython = get_ipython() 

Si tiene una versión anterior:

import IPython.core.ipapi 
ipython = IPython.core.ipapi.get() 

o

import IPython.ipapi 
ipython = IPython.ipapi.get() 

Una vez hecho esto, ejecutar un comando mágico como esto:

ipython.magic("timeit abs(-42)") 

Tenga en cuenta que la secuencia de comandos se debe ejecutar a través de ipython.

+2

Parece que esto ya no funciona bajo IPython 1.x – DaveP

+1

Esto funciona para IPython 1.x: ' de IPython get_ipython' importación ' ipython = get_ipython() ' – suzanshakya

+0

@suzanshakya get_ipython() parece volver Ninguno en una instancia que funcionó previamente. mente apuntando a un ejemplo? – badgley

5

Tanto IPython y el módulo timeit, cuando llama con python -m timeit, ejecutan el mismo bucle con un valor creciente de número hasta que el resultado de temporización supera un cierto umbral que garantiza la medición del tiempo es sobre todo libre de interferencias del sistema operativo.

Puede comparar el IPython implementation of the %timeit magic con el Python timeit standard module para ver que están haciendo casi lo mismo.

Respondiendo a su pregunta, probablemente debería replicar el mismo ciclo hasta que encuentre el valor correcto para el parámetro número.

+0

Ok, solo puedo copiar la parte "principal" del módulo timeit. Me pregunto por qué no está incluido en la biblioteca. –

2

Lo siguiente funciona si uno ejecuta el script de Python interactivamente en IPython. Por ejemplo, test.py:

def f(): 
    # Algorithm 1 
    pass 

def g(): 
    # Algorithm 2 
    pass 

# which one is faster? 
mgc = get_ipython().magic 
mgc(u'%timeit f()') 
mgc(u'%timeit g()') 

continuación, se ejecuta de forma interactiva en IPython

%run -i test.py 

a escupir los tiempos. El interruptor -i es necesario para que las variables estén dentro del alcance. No he descubierto cómo hacerlo sin ejecutar una instancia de IPython, es decir, simplemente importando timeit desde IPython y usándolo como una función. Sin embargo, esta solución funciona para mis propósitos, que es automatizar algunas ejecuciones de tiempo.

1

Una forma de ejecutar la función mágica de ipython probablemente es mediante la incorporación de la instancia de ipython.
Por ejemplo: (la mayoría de los códigos son tomados de ipython website)

from IPython.terminal.embed import InteractiveShellEmbed 

ipshell = InteractiveShellEmbed() 
ipshell.dummy_mode = True 
print('\nTrying to call IPython which is now "dummy":') 
ipshell.magic("%timeit abs(-42)"); 
ipshell() 
print('Nothing happened...') 

Esto puede funcionar mediante el uso de pitón intérprete
PS: usando dummy_mode evitará de invocar shell interactivo.

+1

'desde la importación de IPython get_ipython; ipython = get_ipython() 'devuelve" AttributeError: 'NoneType' "en v4.2.0 pero parece que funciona bien. – 16num

1

De acuerdo con la documentation del módulo timeit.py, cuando timeit se ejecuta en modo de línea de comandos,

If -n is not given, a suitable number of loops is calculated by trying successive powers of 10 until the total time is at least 0.2 seconds.

Esto es lo que hace IPython. Es por ello que el número de bucles es siempre una potencia de 10. Se podría hacer algo similar en su propio código mediante la incorporación de la llamada a t.timeit() dentro de un bucle que se asegura de que no espere demasiado tiempo:

import timeit 
t = timeit.Timer("code(f)", "from __main__ import code, f") 

max_time = 0.2 
N = 0 
curr_time = t.timeit(1) 

while curr_time < max_time: 
    N += 1 
    curr_time = t.timeit(10**N) 

mean_time = curr_time/float(10**N) 

Esto garantizaría que el tiempo de creación de perfiles sea de al menos 0,2 segundos, pero no significativamente mayor, a menos que llamar a la función una vez tarde mucho tiempo.

Cuestiones relacionadas