2012-04-28 55 views
37

Lệnh ma thuật IPython% timeit thực hiện tốt công việc của mình để đo thời gian cần thiết để chạy một số mã Python. Bây giờ, tôi muốn sử dụng một cái gì đó tương tự trong kịch bản Python. Tôi biết về các mô-đun timeit, tuy nhiên, nó có một số nhược điểm, ví dụ, làm thế nào để chọn số lần chạy thích ứng? tức là, mã mặc địnhCách chạy ma thuật IPython từ tập lệnh (hoặc định thời gian tập lệnh Python)

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

chạy mã triệu lần. Lệnh ma thuật% timeit IPyhton thực hiện tự động. Tôi đề nghị rằng tôi có thể sử dụng một cái gì đó giống như mã MATLAB http://www.mathworks.com/matlabcentral/fileexchange/18798

thực hiện tất cả công việc một cách tự động (và cũng cho biết chi phí của hàm lớn).

Làm cách nào tôi có thể gọi% phép thuật thời gian từ tập lệnh Python (hoặc có thể có giải pháp thời gian tốt hơn)?

+7

Nếu bạn đặt nó thành tập lệnh IPython (* .ipy), thì tất cả cú pháp IPython sẽ có sẵn, và bạn chỉ có thể thực hiện '% timeit foo' như bình thường. – minrk

+1

Cảm ơn bạn, đó là một gợi ý tốt. Nhưng tôi sử dụng điều này trong một tập tin chế độ org, và tôi nghĩ rằng nó chỉ biết về python chưa :) –

Trả lời

44

Tùy thuộc vào phiên bản của IPython bạn có. Nếu bạn có 1.x:

from IPython import get_ipython 
ipython = get_ipython() 

Nếu bạn có một phiên bản cũ:

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

hoặc

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

Khi đã xong, chạy một lệnh kỳ diệu như thế này:

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

Lưu ý rằng tập lệnh phải được chạy qua ipython.

+2

Dường như điều này không còn hoạt động trong IPython 1.x – DaveP

+1

Điều này làm việc cho IPython 1.x: 'từ nhập IPython get_ipython' 'ipython = get_ipython()' – suzanshakya

+0

@suzanshakya get_ipython() dường như trả về Không trong một trường hợp mà trước đó đã làm việc. tâm chỉ vào một ví dụ? – badgley

5

Cả IPython và timeit mô-đun, khi được gọi với python -m timeit, thực hiện vòng lặp cùng với một giá trị ngày càng tăng của số cho đến khi kết quả thời gian vượt qua một ngưỡng nhất định mà đảm bảo đo lường thời gian chủ yếu là miễn nhiễu hệ điều hành.

Bạn có thể so sánh số IPython implementation of the %timeit magic với số Python timeit standard module để thấy rằng chúng đang hoạt động giống nhau.

Vì vậy, trả lời câu hỏi của bạn, có lẽ bạn nên sao chép cùng một vòng lặp cho đến khi bạn tìm thấy giá trị chính xác cho thông số số.

+0

Ok, tôi chỉ có thể sao chép phần "chính" của mô-đun timeit. Tự hỏi tại sao nó không được đưa vào thư viện. –

2

Các công trình sau đây hoạt động nếu chạy một tập lệnh Python tương tác trong IPython. Ví dụ, 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()') 

Sau đó chạy nó một cách tương tác trong IPython

%run -i test.py 

để nhổ ra timings. Công tắc -i là cần thiết để các biến nằm trong phạm vi. Tôi đã không tìm ra cách để làm điều này mà không cần chạy một cá thể IPython, tức là, bằng cách nhập timeit từ IPython và sử dụng nó như một hàm. Tuy nhiên, giải pháp này làm việc cho mục đích của tôi, đó là để tự động hóa một số thời gian chạy.

1

Một cách để chạy chức năng ma thuật ipython có thể đang sử dụng cá thể nhúng ipython.
Ví dụ: (hầu hết các mã được vay mượn từ 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...') 

này có thể làm việc bằng cách sử dụng python phiên dịch
PS: sử dụng dummy_mode sẽ ngăn chặn từ cách gọi vỏ tương tác.

+1

'từ IPython import get_ipython; ipython = get_ipython() 'đang trả về" AttributeError: 'NoneType' "trên v4.2.0 nhưng điều này có vẻ hoạt động tốt. – 16num

1

Theo documentation của module timeit.py, khi timeit đang chạy trong chế độ dòng lệnh,

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.

Đây là những gì IPython làm. Đó là lý do tại sao số vòng lặp luôn luôn là một sức mạnh của 10 Bạn có thể làm điều gì đó tương tự trong mã của riêng bạn bằng cách nhúng các cuộc gọi đến t.timeit() bên trong một vòng lặp mà làm cho chắc chắn rằng bạn không chờ đợi quá lâu:

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) 

Điều này sẽ đảm bảo rằng thời gian lược tả ít nhất là 0,2 giây, nhưng không đáng kể nhiều hơn --- trừ khi gọi hàm một lần mất một thời gian dài.

Các vấn đề liên quan