जवाबों:
जिस तरह से टाइमटाइम काम करता है वह एक बार सेटअप कोड चलाने और फिर कई बार बयानों की श्रृंखला में कॉल करने का होता है। इसलिए, यदि आप छंटाई का परीक्षण करना चाहते हैं, तो कुछ देखभाल की आवश्यकता होती है, ताकि इन-प्लेस सॉर्ट पर एक पास पहले से ही सॉर्ट किए गए डेटा के साथ पास को प्रभावित न करे (जो निश्चित रूप से, Timsort वास्तव में चमक देगा क्योंकि यह सबसे अच्छा प्रदर्शन करता है जब डेटा पहले से ही आंशिक रूप से ऑर्डर किया गया हो)।
यहाँ एक उदाहरण दिया गया है कि छंटाई के लिए परीक्षण कैसे सेट करें:
>>> import timeit
>>> setup = '''
import random
random.seed('slartibartfast')
s = [random.random() for i in range(1000)]
timsort = list.sort
'''
>>> print min(timeit.Timer('a=s[:]; timsort(a)', setup=setup).repeat(7, 1000))
0.334147930145
ध्यान दें कि कथनों की श्रृंखला हर पास पर अनसोल्ड डेटा की एक नई प्रतिलिपि बनाती है।
इसके अलावा, माप सूट को सात बार चलाने और केवल सबसे अच्छा समय रखने की समय तकनीक पर ध्यान दें - यह वास्तव में आपके सिस्टम पर चल रही अन्य प्रक्रियाओं के कारण माप विकृतियों को कम करने में मदद कर सकता है।
वे सही समय का उपयोग करने के लिए मेरी युक्तियां हैं। उम्मीद है की यह मदद करेगा :-)
.repeat(7,1000)
पहले से ही (एक ही बीज का उपयोग करके) ऐसा करता है! तो आपका समाधान सही IMO है।
.repeat(7, 1000)
बनाम .repeat(2, 3500)
बनाम .repeat(35, 200
) इस बात पर निर्भर करना चाहिए कि इनपुट परिवर्तनशीलता के कारण सिस्टम लोड के कारण त्रुटि की तुलना कैसे होती है। चरम स्थिति में यदि आपका सिस्टम हमेशा भारी लोड के अधीन है, और आपको निष्पादन समय वितरण के बाईं ओर एक लंबी पतली पूंछ दिखाई देती है (जब आप इसे एक दुर्लभ निष्क्रिय अवस्था में पकड़ते हैं), तो आप इससे भी .repeat(7000,1)
अधिक उपयोगी हो सकते हैं .repeat(7,1000)
यदि आप 7000 से अधिक रन बजट नहीं कर सकते।
यदि आप timeit
एक इंटरैक्टिव पायथन सत्र में उपयोग करना चाहते हैं, तो दो सुविधाजनक विकल्प हैं:
IPython शेल का उपयोग करें । यह सुविधाजनक %timeit
विशेष समारोह पेश करता है:
In [1]: def f(x):
...: return x*x
...:
In [2]: %timeit for x in range(100): f(x)
100000 loops, best of 3: 20.3 us per loop
मानक पायथन दुभाषिया में, आप __main__
सेटअप सत्र से आयात करके इंटरेक्टिव सत्र के दौरान पहले से परिभाषित कार्यों और अन्य नामों तक पहुँच सकते हैं :
>>> def f(x):
... return x * x
...
>>> import timeit
>>> timeit.repeat("for x in range(100): f(x)", "from __main__ import f",
number=100000)
[2.0640320777893066, 2.0876040458679199, 2.0520210266113281]
from __main__ import f
तकनीक दिखाने के लिए +1 । मुझे नहीं लगता कि यह उतना व्यापक रूप से जाना जाता है जितना इसे होना चाहिए। यह इस तरह के मामलों में उपयोगी है जहां एक फ़ंक्शन या विधि कॉल समयबद्ध हो रही है। अन्य मामलों में (चरणों की एक श्रृंखला का समय), यह कम सहायक है क्योंकि यह फ़ंक्शन कॉल ओवरहेड का परिचय देता है।
%timeit f(x)
sys._getframe(N).f_globals
) का ग्लोबल्स शुरुआत से ही डिफ़ॉल्ट होना चाहिए था।
मैं आपको एक रहस्य पर जाने दूँगा: उपयोग करने का सबसे अच्छा तरीका timeit
कमांड लाइन पर है।
कमांड लाइन पर, timeit
उचित सांख्यिकीय विश्लेषण करता है: यह आपको बताता है कि सबसे कम समय कितना समय लगा। यह अच्छा है क्योंकि समय में सभी त्रुटि सकारात्मक है। इसलिए कम से कम समय में इसमें सबसे कम त्रुटि है। नकारात्मक त्रुटि प्राप्त करने का कोई तरीका नहीं है क्योंकि कंप्यूटर कभी भी तेजी से गणना नहीं कर सकता है क्योंकि यह गणना कर सकता है!
तो, कमांड लाइन इंटरफ़ेस:
%~> python -m timeit "1 + 2"
10000000 loops, best of 3: 0.0468 usec per loop
यह काफी सरल है, एह?
आप सामान सेट कर सकते हैं:
%~> python -m timeit -s "x = range(10000)" "sum(x)"
1000 loops, best of 3: 543 usec per loop
जो उपयोगी है, भी!
यदि आप कई लाइनें चाहते हैं, तो आप शेल के स्वचालित निरंतरता का उपयोग कर सकते हैं या अलग-अलग तर्क का उपयोग कर सकते हैं:
%~> python -m timeit -s "x = range(10000)" -s "y = range(100)" "sum(x)" "min(y)"
1000 loops, best of 3: 554 usec per loop
का एक सेटअप देता है
x = range(1000)
y = range(100)
और बार
sum(x)
min(y)
यदि आप लंबी स्क्रिप्ट चाहते हैं तो आपको timeit
पायथन स्क्रिप्ट के अंदर जाने के लिए लुभाया जा सकता है । मैं इससे बचने का सुझाव देता हूं क्योंकि विश्लेषण और समय कमांड लाइन पर बेहतर है। इसके बजाय, मैं शेल स्क्रिप्ट बनाने के लिए जाता हूं:
SETUP="
... # lots of stuff
"
echo Minmod arr1
python -m timeit -s "$SETUP" "Minmod(arr1)"
echo pure_minmod arr1
python -m timeit -s "$SETUP" "pure_minmod(arr1)"
echo better_minmod arr1
python -m timeit -s "$SETUP" "better_minmod(arr1)"
... etc
यह कई प्रारंभिकताओं के कारण थोड़ा अधिक समय ले सकता है, लेकिन आम तौर पर यह कोई बड़ी बात नहीं है।
लेकिन क्या होगा अगर आप अपने मॉड्यूल के अंदर का उपयोग करना चाहते हैंtimeit
?
वैसे, सरल तरीका यह है:
def function(...):
...
timeit.Timer(function).timeit(number=NUMBER)
और वह आपको कम से कम ( कम से कम नहीं !) समय देता है जो उस संख्या को चलाता है।
एक अच्छा विश्लेषण प्राप्त करने के लिए, उपयोग करें .repeat
और न्यूनतम लें:
min(timeit.Timer(function).repeat(repeat=REPEATS, number=NUMBER))
आपको सामान्य रूप से निचले ओवरहेड के functools.partial
बजाय इसके साथ गठबंधन करना चाहिए lambda: ...
। इस प्रकार आपके पास कुछ ऐसा हो सकता है:
from functools import partial
def to_time(items):
...
test_items = [1, 2, 3] * 100
times = timeit.Timer(partial(to_time, test_items)).repeat(3, 1000)
# Divide by the number of repeats
time_taken = min(times) / 1000
आप भी कर सकते हैं:
timeit.timeit("...", setup="from __main__ import ...", number=NUMBER)
जो आपको कमांड-लाइन से इंटरफ़ेस के करीब कुछ देगा , लेकिन बहुत कम शांत तरीके से। "from __main__ import ..."
आप के द्वारा बनाई गई कृत्रिम वातावरण के अंदर अपने मुख्य मॉड्यूल से कोड का उपयोग करने देता timeit
।
यह ध्यान देने योग्य है कि यह एक सुविधा आवरण है Timer(...).timeit(...)
और इसलिए यह समय पर विशेष रूप से अच्छा नहीं है। Timer(...).repeat(...)
जैसा कि मैंने ऊपर दिखाया है मैं व्यक्तिगत रूप से उपयोग करना पसंद करता हूं।
timeit
हर जगह उस होल्ड के साथ कुछ कैविएट हैं ।
ओवरहेड का हिसाब नहीं है। कहो कि आप समय x += 1
निकालना चाहते हैं , यह जानने के लिए कि कितना समय लगता है:
>>> python -m timeit -s "x = 0" "x += 1"
10000000 loops, best of 3: 0.0476 usec per loop
खैर, यह 0.0476 47s नहीं है । आप केवल यह जानते हैं कि यह उससे कम है। सभी त्रुटि सकारात्मक है।
तो कोशिश करो और शुद्ध उपरि खोजें:
>>> python -m timeit -s "x = 0" ""
100000000 loops, best of 3: 0.014 usec per loop
यह एक अच्छा 30% ओवरहेड सिर्फ समय से है! यह बड़े पैमाने पर सापेक्ष समय को कम कर सकता है। लेकिन आप केवल जोड़ने की टाइमिंग के बारे में वास्तव में परवाह करते थे ; x
ओवरहेड में शामिल करने के लिए लुक-अप टाइमिंग की भी आवश्यकता है:
>>> python -m timeit -s "x = 0" "x"
100000000 loops, best of 3: 0.0166 usec per loop
अंतर बहुत बड़ा नहीं है, लेकिन यह वहां है।
म्यूट करने के तरीके खतरनाक हैं।
>>> python -m timeit -s "x = [0]*100000" "while x: x.pop()"
10000000 loops, best of 3: 0.0436 usec per loop
लेकिन यह पूरी तरह से गलत है! x
पहली पुनरावृत्ति के बाद खाली सूची है। आपको फिर से संगठित करने की आवश्यकता होगी:
>>> python -m timeit "x = [0]*100000" "while x: x.pop()"
100 loops, best of 3: 9.79 msec per loop
लेकिन फिर आपके पास बहुत सारे ओवरहेड हैं। उसके लिए अलग से खाता।
>>> python -m timeit "x = [0]*100000"
1000 loops, best of 3: 261 usec per loop
ध्यान दें कि ओवरहेड को घटाना यहां उचित है क्योंकि ओवरहेड उस समय का एक छोटा-ईश अंश है।
आपके उदाहरण के लिए, यह ध्यान देने योग्य है कि प्रविष्टि सॉर्ट और टिम सॉर्ट दोनों पहले से ही सॉर्ट किए गए सूचियों के लिए पूरी तरह से असामान्य समय व्यवहार हैं। इसका मतलब है कि random.shuffle
अगर आप अपनी टाइमिंग को खत्म करने से बचना चाहते हैं तो आपको एक तरह की आवश्यकता होगी ।
timeit
में रुचि हो सकती है लेकिन कमांड लाइन के समान कार्य कर रहे हैं? ।
timeit
एक pass
कथन निष्पादित करता है , जो निश्चित रूप से, कुछ समय लेता है। यदि कोई तर्क दिया जाता है, तो उसे क्रियान्वित नहीं कियाpass
जाएगा , इसलिए हर समय से कुछ usecs घटाना गलत होगा। 0.014
मेरे लिए, यह सबसे तेज़ तरीका है:
import timeit
def foo():
print("here is my code to time...")
timeit.timeit(stmt=foo, number=1234567)
# Генерация целых чисел
def gen_prime(x):
multiples = []
results = []
for i in range(2, x+1):
if i not in multiples:
results.append(i)
for j in range(i*i, x+1, i):
multiples.append(j)
return results
import timeit
# Засекаем время
start_time = timeit.default_timer()
gen_prime(3000)
print(timeit.default_timer() - start_time)
# start_time = timeit.default_timer()
# gen_prime(1001)
# print(timeit.default_timer() - start_time)
यह महान काम करता है:
python -m timeit -c "$(cat file_name.py)"
निम्न में से प्रत्येक में एक ही शब्दकोश को सेटअप करने देता है और निष्पादन समय का परीक्षण करता है।
सेटअप तर्क मूल रूप से शब्दकोश सेट कर रहा है
नंबर को 1000000 बार कोड चलाना है। सेटअप नहीं, लेकिन stmt
जब आप इसे चलाते हैं, तो आप देख सकते हैं कि सूचकांक प्राप्त करने की तुलना में तेज़ है। आप इसे कई बार देख सकते हैं।
कोड मूल रूप से कोश में c का मान प्राप्त करने का प्रयास करता है।
import timeit
print('Getting value of C by index:', timeit.timeit(stmt="mydict['c']", setup="mydict={'a':5, 'b':6, 'c':7}", number=1000000))
print('Getting value of C by get:', timeit.timeit(stmt="mydict.get('c')", setup="mydict={'a':5, 'b':6, 'c':7}", number=1000000))
यहाँ मेरे परिणाम हैं, तुम्हारा अलग होगा।
सूचकांक द्वारा: 0.20900007452246427
द्वारा प्राप्त करें: 0.54841166886888
बस अपने पूरे कोड को समयसीमा के तर्क के रूप में पास करें:
import timeit
print(timeit.timeit(
"""
limit = 10000
prime_list = [i for i in range(2, limit+1)]
for prime in prime_list:
for elem in range(prime*2, max(prime_list)+1, prime):
if elem in prime_list:
prime_list.remove(elem)
"""
, number=10))
import timeit
def oct(x):
return x*x
timeit.Timer("for x in range(100): oct(x)", "gc.enable()").timeit()
gc.enable()
?
बिल्ट-इन टाइमिट मॉड्यूल IPython कमांड लाइन से सबसे अच्छा काम करता है।
एक मॉड्यूल के भीतर समय से कार्य करने के लिए:
from timeit import default_timer as timer
import sys
def timefunc(func, *args, **kwargs):
"""Time a function.
args:
iterations=3
Usage example:
timeit(myfunc, 1, b=2)
"""
try:
iterations = kwargs.pop('iterations')
except KeyError:
iterations = 3
elapsed = sys.maxsize
for _ in range(iterations):
start = timer()
result = func(*args, **kwargs)
elapsed = min(timer() - start, elapsed)
print(('Best of {} {}(): {:.9f}'.format(iterations, func.__name__, elapsed)))
return result
मापदंडों को स्वीकार करने वाले फ़ंक्शन के साथ पायथन आरईपीएल दुभाषिया का उपयोग कैसे करें, इसका उदाहरण।
>>> import timeit
>>> def naive_func(x):
... a = 0
... for i in range(a):
... a += i
... return a
>>> def wrapper(func, *args, **kwargs):
... def wrapper():
... return func(*args, **kwargs)
... return wrapper
>>> wrapped = wrapper(naive_func, 1_000)
>>> timeit.timeit(wrapped, number=1_000_000)
0.4458435332577161
आप दो फ़ंक्शन बनाएंगे और फिर इसके समान कुछ चलाएंगे। ध्यान दें, आप सेब से सेब की तुलना करने के लिए एक ही संख्या में निष्पादन / चलाने का चयन करना चाहते हैं।
यह पायथन 3.7 के तहत परीक्षण किया गया था।
यहाँ इसे कॉपी करने में आसानी के लिए कोड है
!/usr/local/bin/python3
import timeit
def fibonacci(n):
"""
Returns the n-th Fibonacci number.
"""
if(n == 0):
result = 0
elif(n == 1):
result = 1
else:
result = fibonacci(n-1) + fibonacci(n-2)
return result
if __name__ == '__main__':
import timeit
t1 = timeit.Timer("fibonacci(13)", "from __main__ import fibonacci")
print("fibonacci ran:",t1.timeit(number=1000), "milliseconds")
timsort(a)
और अंतर लें :-)