Я хочу сравнить время выполнения двух фрагментов и посмотреть, какой из них быстрее. Итак, мне нужен точный метод измерения времени выполнения моих фрагментов Python.
Я уже пытался использовать time.time()
, time.process_time()
, time.perf_counter_ns()
, а также timeit.timeit()
, но со всеми из них у меня возникают одни и те же проблемы. То есть: когда я использую любой из вышеперечисленных методов для измерения времени выполнения ТОГО ЖЕ фрагмента, он возвращает другое значение каждый раз, когда я его запускаю. И эта вариация несколько значительна, поскольку я не могу надежно использовать их для сравнения разницы во времени выполнения двух фрагментов кода.
В качестве примера я запускаю следующий код в своем коллабе Google:
import time
t1 = time.perf_counter()
sample_list = []
for i in range(1000000):
sample_list.append(i)
t2 = time.perf_counter()
print(t2 - t1)
Я запускал выше код 10 раз, и разница в моих результатах составляет около 50% (минимальное значение = 0,14, максимальное значение = 0,28).
Любые альтернативы?
Термин, который вы ищете, — профилирование: stackoverflow.com/questions/582336/…
Я добавил пример, который я запускаю прямо сейчас.
Google colab является сбивающим с толку фактором. Вы работаете на сервере со многими соавторами. Анализ производительности следует проводить в как можно более строго контролируемой среде. Даже ноутбук с разной тактовой частотой может быть проблемой.
Время выполнения данного фрагмента кода почти всегда будет разным при каждом его запуске. Большинство инструментов, доступных для профилирования одной функции/фрагмента кода, учитывают это и запускают код несколько раз, чтобы обеспечить среднее время выполнения. Причина этого в том, что на вашем компьютере запущены другие процессы, а ресурсы не всегда распределяются одинаково, поэтому невозможно контролировать каждую переменную, чтобы вы получали одинаковое время выполнения для каждого запуска.
Один из самых простых способов профилирования данной функции или короткого фрагмента кода — использование «волшебной» команды %timeit в ipython. Пример:
>>> %timeit 1 + 1
8.41 ns ± 0.0181 ns per loop (mean ± std. dev. of 7 runs, 100,000,000 loops each)
Это также позволяет вам вводить многострочный блок кода, если вы используете %%timeit
вместо %timeit
.
Библиотеку timeit можно использовать независимо, но часто ее проще использовать в интерактивном сеансе ipython.
Дополнительные ресурсы:
timeit также дает разные результаты при одних и тех же условиях (один и тот же фрагмент выполняется одинаковое количество раз). Если нет надежного метода измерения времени выполнения фрагмента, как мы действительно хотим доказать, что один код быстрее другого при оптимизации? Я помню видео на YouTube, сравнивающее время выполнения факториальной функции при расчете на основе рекурсии и циклов. Ютубер использовал метод time.time() и завершил цикл быстрее. Затем я попробовал свою систему и обнаружил, что рекурсия работает быстрее.
Если нет статистически значимой разницы между временем выполнения, возвращаемым timeit
для двух разных реализаций, выполняющих одну и ту же цель, вам следует просто выбрать ту, которая более читабельна/понятнее. Различия в версии Python и в том, где вы запускаете данную программу, могут привести к некоторым различиям, которые вы никогда не устраните полностью. Это справедливо для любого языка программирования.
Кроме того, time.time()
не следует использовать для измерения времени выполнения чего-либо. Не гарантируется получение точных значений в случае високосных секунд и т.п. Для этого лучше использовать time.montotonic()
.
Спасибо за отзыв. Я где-то читал, что отключение сборки мусора также помогает увеличить точность измерения времени выполнения.
timeit
запускает сниппет много раз (по умолчанию 1 миллион). Если это бит кода, связанный с процессором, он должен быть одинаковым для всех прогонов. Я замечаю дрейф < 10%. Если делать ввод-вывод, это другая история. У вас есть пример, который мы могли бы попробовать?