Я понимаю концепцию того, что timeit
делает, но я не уверен, как реализовать это в моем коде.
Как я могу сравнить две функции, скажем, insertion_sort
и tim_sort
, с timeit
?
Способ работы timeit состоит в том, чтобы один раз запустить установочный код, а затем делать повторные вызовы для серии операторов. Так что, если вы хотите проверить сортировку, требуется некоторая осторожность, чтобы один проход при сортировке на месте не влиял на следующий проход с уже отсортированными данными (что, конечно, сделает 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
Обратите внимание, что серия операторов создает свежую копию несортированных данных на каждом проходе.
Кроме того, обратите внимание на методику синхронизации запуска набора измерений семь раз и сохранения только лучшего времени - это действительно может помочь уменьшить искажения измерения из-за других процессов, выполняющихся в вашей системе.
Это мои советы по правильному использованию времени. Надеюсь это поможет :-)
timsort(a)
и возьмите разницу :-).repeat(7,1000)
уже делаете это (используя то же семя)! Таким образом, ваше решение идеально подходит для IMO..repeat(7, 1000)
против и.repeat(2, 3500)
против.repeat(35, 200
), должно зависеть от того, как ошибка из-за загрузки системы сравнивается с ошибкой из-за изменчивости ввода. В крайнем случае, если ваша система всегда находится под большой нагрузкой, и вы видите длинный тонкий хвост слева от распределения времени выполнения (когда вы ловите его в редком состоянии простоя), вы можете даже.repeat(7000,1)
оказаться более полезным, чем.repeat(7,1000)
если бы вы не может бюджетировать более 7000 пробежек.Если вы хотите использовать
timeit
в интерактивном сеансе Python, есть два удобных варианта:Используйте оболочку IPython . Он имеет удобную
%timeit
специальную функцию:В стандартном интерпретаторе Python вы можете получить доступ к функциям и другим именам, которые вы определили ранее во время интерактивного сеанса, импортировав их из
__main__
оператора setup:источник
from __main__ import f
техники. Я не думаю, что это так широко известно, как должно быть. Это полезно в случаях, подобных этому, когда происходит вызов функции или метода. В других случаях (синхронизация ряда шагов) это менее полезно, потому что вводит издержки вызова функции.%timeit f(x)
sys._getframe(N).f_globals
) должны были быть по умолчанию с самого начала.Я открою вам секрет: лучший способ использовать
timeit
это в командной строке.В командной строке
timeit
выполняет надлежащий статистический анализ: он сообщает, сколько времени занял самый короткий пробег. Это хорошо, потому что все ошибки во времени положительны. Поэтому самое короткое время содержит наименьшую ошибку. Нет способа получить отрицательную ошибку, потому что компьютер не может вычислить быстрее, чем он может вычислить!Итак, интерфейс командной строки:
Это довольно просто, а?
Вы можете настроить вещи:
что тоже полезно!
Если вам нужно несколько строк, вы можете использовать автоматическое продолжение оболочки или использовать отдельные аргументы:
Это дает настройку
и раз
Если вы хотите иметь более длинные сценарии, у вас может возникнуть желание перейти
timeit
внутрь сценария Python. Я предлагаю избегать этого, потому что анализ и сроки просто лучше в командной строке. Вместо этого я склонен делать сценарии оболочки:Это может занять немного больше времени из-за множественных инициализаций, но обычно это не имеет большого значения.
Но что, если вы хотите использовать
timeit
внутри вашего модуля?Ну, простой способ сделать это:
и это дает вам кумулятивное ( не минимальное!) время для выполнения этого количества раз.
Чтобы получить хороший анализ, используйте
.repeat
и возьмите минимум:Вы должны обычно комбинировать это с
functools.partial
вместо того,lambda: ...
чтобы снизить накладные расходы. Таким образом, вы можете получить что-то вроде:Вы также можете сделать:
что даст вам что-то ближе к интерфейсу из командной строки, но гораздо менее круто.
"from __main__ import ..."
Позволяет использовать код из основного модуля в искусственной среде , созданнойtimeit
.Стоит отметить, что это удобная оболочка,
Timer(...).timeit(...)
и поэтому она не особенно хороша во времени. Я лично предпочитаю использовать,Timer(...).repeat(...)
как я показал выше.Предупреждения
Есть несколько предостережений с
timeit
этим повсюду.Накладные расходы не учитываются. Скажем, вы хотите время
x += 1
, чтобы узнать, сколько времени занимает добавление:Ну, это не 0,0476 мкс. Вы только знаете, что это меньше, чем это. Вся ошибка положительная.
Поэтому постарайтесь найти чистые накладные расходы:
Это хорошие 30% накладные расходы только от времени! Это может сильно исказить относительные значения времени. Но вы только действительно заботились о добавлении времени; временные параметры поиска
x
также должны быть включены в накладные расходы:Разница не намного больше, но она есть.
Методы мутации опасны.
Но это совершенно неправильно!
x
пустой список после первой итерации. Вам нужно будет повторно инициализировать:Но тогда у вас много накладных расходов. Учитывайте это отдельно.
Обратите внимание, что вычитание служебных данных здесь разумно только потому, что накладные расходы составляют небольшую долю времени.
Для вашего примера стоит отметить, что и сортировка вставкой, и сортировка Тимом имеют совершенно необычные временные характеристики для уже отсортированных списков. Это означает, что вы будете нуждаться в
random.shuffle
перерывах между родами, если вы хотите избежать разрушения времени.источник
timeit
из программы, но функционирование так же, как в командной строке? ,timeit
выполняетpass
оператор, когда аргументы не заданы, что, конечно, занимает некоторое время. Если будут заданы какие-либо аргументы,pass
они не будут выполнены, поэтому вычитание некоторых0.014
usecs из каждого тайминга было бы некорректным.Если вы хотите быстро сравнить два блока кода / функции, вы можете сделать:
источник
Я считаю, что самый простой способ использовать timeit из командной строки:
Учитывая test.py :
Запустите время так:
источник
для меня это самый быстрый способ:
источник
источник
Это прекрасно работает:
источник
Давайте установим один и тот же словарь в каждом из следующих пунктов и протестируем время выполнения.
Аргумент настройки в основном настраивает словарь
Номер для запуска кода 1000000 раз. Не настройка, а stmt
Когда вы запустите это, вы увидите, что индекс намного быстрее, чем get. Вы можете запустить его несколько раз, чтобы увидеть.
Код в основном пытается получить значение c в словаре.
Вот мои результаты, ваши будут отличаться.
по индексу: 0.20900007452246427
по получению: 0.54841166886888
источник
просто передайте весь код в качестве аргумента timeit:
источник
источник
gc.enable()
?Встроенный модуль timeit лучше всего работает из командной строки IPython.
Чтобы функции времени изнутри модуля:
источник
Пример использования интерпретатора Python REPL с функцией, принимающей параметры.
источник
Вы должны создать две функции, а затем запустить нечто похожее на это. Обратите внимание, вы хотите выбрать одинаковое количество выполнений / прогонов, чтобы сравнить яблоко с яблоком.
Это было проверено в Python 3.7.
Вот код для простоты его копирования
источник