web-dev-qa-db-fra.com

Comment exécuter une magie IPython à partir d'un script (ou chronométrer un Python)

La commande magique IPython% timeit fait bien son travail pour mesurer le temps requis pour exécuter du code Python. Maintenant, je veux utiliser quelque chose d'analogue dans le script Python . Je connais le module timeit, cependant, il a plusieurs inconvénients, par exemple, comment sélectionner le nombre d'exécutions de manière adaptative? Ie, le code par défaut

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

exécute le code des millions de fois. La commande magique% timeit IPyhton le fait automatiquement. Je suggère que je puisse utiliser quelque chose comme le code MATLAB http://www.mathworks.com/matlabcentral/fileexchange/18798

cela fait tout le travail automatiquement (et indique également si la surcharge de la fonction est importante).

Comment puis-je appeler% timeit magic à partir d'un script Python (ou peut-être existe-t-il une meilleure solution de synchronisation)?

46
Ivan Oseledets

Cela dépend un peu de la version d'IPython dont vous disposez. Si vous avez 1.x:

from IPython import get_ipython
ipython = get_ipython()

Si vous avez une ancienne version:

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

ou

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

ne fois cela fait, exécutez une commande magique comme celle-ci:

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

Notez que le script doit être exécuté via ipython.

56
user2261139

IPython et le module timeit, lorsqu'ils sont appelés avec python -m timeit, exécutez la même boucle avec une valeur croissante de nombre jusqu'à ce que le résultat du chronométrage dépasse un certain seuil qui garantit que la mesure du temps est en grande partie exempte de système d'exploitation interférences.

Vous pouvez comparer le implémentation IPython du %timeit magic avec le module standard Python timeit pour voir qu'ils font pratiquement la même chose.

Donc, pour répondre à votre question, vous devriez probablement répliquer la même boucle jusqu'à ce que vous trouviez la valeur correcte pour le paramètre numérique .

6
C2H5OH

Ce qui suit fonctionne si l'on exécute le script Python de manière interactive dans IPython. Par exemple, 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()')

Exécutez-le ensuite de manière interactive dans IPython

%run -i test.py

pour cracher les horaires. Le -i le commutateur est nécessaire pour que les variables soient dans la portée. Je n'ai pas compris comment faire cela sans exécuter une instance IPython, c'est-à-dire en important simplement timeit depuis IPython et en l'utilisant comme fonction. Cependant, cette solution fonctionne pour mes besoins, qui consiste à automatiser certaines exécutions de synchronisation.

3
Stefan

Selon la documentation du module timeit.py, Lorsque timeit est exécuté en mode ligne de commande,

Si -n n'est pas donné, un nombre approprié de boucles est calculé en essayant des puissances successives de 10 jusqu'à ce que le temps total soit d'au moins 0,2 seconde.

C'est ce que fait IPython. C'est pourquoi le nombre de boucles est toujours une puissance de 10. Vous pouvez faire quelque chose de similaire dans votre propre code en incorporant l'appel à t.timeit() dans une boucle qui vous assure de ne pas attendre trop longtemps:

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)

Cela garantirait que le temps de profilage est d'au moins 0,2 seconde, mais pas beaucoup plus --- à moins que l'appel de la fonction ne prenne beaucoup de temps.

2
Jesse

Une façon d'exécuter la fonction magique ipython est probablement d'utiliser une instance ipython intégrée.
Par exemple: (la plupart des codes sont empruntés à site Web ipython )

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...')

Cela peut fonctionner en utilisant python interpreter
PS: l'utilisation de dummy_mode empêchera d'invoquer le shell interactif.

1
Rene Wang