Время исполнения программы python

Как можно засечь время выполнения каждой из функций и суммарное время выполнения программы

Есть код с тремя сотрировками, есть отчет о времени выполнения программы. Как можно засечь время выполнения каждой из функций и суммарное время выполнения программы. Еще, если не сложно, посоветуйте как сократить программу.

import numpy import time start_time = time.clock() def selection(arrayToSort): a = arrayToSort for i in range(len(a)): idxMin = i for j in range(i+1, len(a)): if a[j] < a[idxMin]: idxMin = j tmp = a[idxMin] a[idxMin] = a[i] a[i] = tmp return a def insertion(arrayToSort): a = arrayToSort for i in range(len(a)): v = a[i] j = i while (a[j-1] >v) and (j > 0): a[j] = a[j-1] j = j - 1 a[j] = v return a def bubble(arrayToSort): a = arrayToSort for i in range(len(a),0,-1): for j in range(1, i): if a[j-1] > a[j]: tmp = a[j-1] a[j-1] = a[j] a[j] = tmp return a ary = numpy.random.choice(100000, 100000, replace=False) print (len(ary), ary[:5]) print (len(selection(ary)), selection(ary)[:5]) print (len(insertion(ary)), insertion(ary)[:5]) print (len(bubble(ary)), bubble(ary)[:5]) print (" s".format(time.clock() - start_time)) 

лучше отдельно задавать вопросы «Как можно засечь время выполнения каждой из функций и суммарное время выполнения программы.» и «как сократить программу» для второго вопроса можно code-review метку выставить (прочтите описание метки и посмотрите примеры существующих вопрос, чтобы убедиться чего ожидать и подходит ли это в вашем случае)

стоит упомянуть: 1- a = arrayToSort не копирует arrayToSort поэтому ваши функции изменяют ввод по месту. В таких случаях в Питоне принято, чтобы функции ничего не возвращали (сравните L.sort() и sorted(L) — последнее не изменяет L , поэтому sorted() возвращает значение. 2- поэлементный невекторизованный доступ к numpy массивам крайне медленный. В вашем случае даже обычные Питон списки вероятно были бы быстрее. 3- numpy.random.choice(100000, 100000, replace=False) можно на просто numpy.random.permutation(100000) заменить (тот же результат, но более ясно и вероятно эффективно).

Читайте также:  Javascript remove javascript file

4 ответа 4

Чтобы измерить время выполнения программы, можно time команду использовать (часто встроена в shell):

$ time python -c 'import time; time.sleep(1)' python -c 'import time; time.sleep(1)' 0.01s user 0.00s system 1% cpu 1.021 total 

Чтобы посмотреть сколько времени индивидуальные функции занимают, можно cProfile модуль использовать:

$ python -m cProfile -s time your_module.py 

В графическом виде результаты удобно в KCachegrind просматривать. Пример команд. Больше вариантов: How can you profile a script?

line_profiler позволяет построчно сравнение производить.

timeit

Чтобы измерить производительность отдельной функции, можно timeit модуль использовать:

$ python -m timeit -s 'from insertion_sort import sorted; L = list(range(10**5))' 'sorted(L)' 

Тот же интерфейс предоставляет pyperf модуль (помимо прочего):

$ python -m pyperf timeit -s '. ' 'sorted(L)' 

Для интерактивной работы можно %timeit magic в ipython/jupyter notebook использовать.

reporttime.py

Оптимизируя выполнение функции, стоит убедиться что она работает корректно (тесты), что изменения действительно ускорили её работу (сравнение производительности). Для этого можно pytest-benchmark использовать.

Для удобства сравнения производительности нескольких алгоритмов, можно автоматически соответствующие функции собрать по общему префиксу в имени ( get_functions_with_prefix() ). К примеру, если функции в вопросе можно назвать: sorted_selection , sorted_insertion , sorted_bubble и поместить в daedra.py файл:

#!/usr/bin/env python import random from reporttime import get_functions_with_prefix, measure import daedra funcs = get_functions_with_prefix('sorted_', module=daedra) for comment, L in [ ("all same", [1] * 10**3), ("range", list(range(10**3))), ("random", list(range(10**3)))]: if comment == "random": random.shuffle(L) measure(funcs, args=[L], comment=comment) 

где reporttime.py . measure() функция измеряет производительность функций похожим на python -mtimeit команду способом.

Результаты

name time ratio comment sorted_insertion 184 usec 1.00 all same sorted_selection 55.9 msec 303.86 all same sorted_bubble 59.4 msec 322.92 all same name time ratio comment sorted_insertion 186 usec 1.00 range sorted_selection 57.7 msec 309.44 range sorted_bubble 60.8 msec 326.40 range name time ratio comment sorted_selection 58 msec 1.00 random sorted_insertion 66.2 msec 1.14 random sorted_bubble 119 msec 2.05 random 

Таблица показывает, что на уже отсортированном вводе sorted_insertion() функция заметно выигрывает (в этом случае линейное время для этой функции требуется по сравнению с квадратичным для sorted_selection() и sorted_bubble() ). Для случайного ввода, производительность примерно одинаковая. sorted_bubble() хуже во всех вариантах.

make-figures.py

В качестве альтернативы можно декоратор использовать такой как @to_compare , чтобы собрать функции для сравнения и адаптировать их для make-figures.py скрипта, который измеряет производительность и строит графики. Пример.

Чтобы нарисовать время выполнения функций для разных вводов:

#!/usr/bin/env python #file: plot_daedra.py import random def seq_range(n): return list(range(n)) def seq_random(n): L = seq_range(n) random.shuffle(L) return L if __name__ == '__main__': import sys from subprocess import check_call import daedra from reporttime import get_functions_with_prefix # measure performance and plot it check_call(["make-figures.py"] + [ "--sort-function=daedra." + f.__name__ for f in get_functions_with_prefix('sorted_', module=daedra) ] + [ "--sequence-creator=plot_daedra." + f.__name__ for f in get_functions_with_prefix('seq_') ] + sys.argv[1:]) 

seq_range() , seq_random() задают два типа ввода (уже отсортированный и случайный соответственно). Можно определить дополнительные типы, определив seq_*(n) функцию. Пример запуска:

$ PYTHONPATH=. python plot_daedra.py --maxn 1024 

PYTHONPATH=. используется, чтобы make-figures.py смог найти plot_daedra модуль (с seq_range , seq_random функциями) в текущей директории. —maxn определяет наибольшее n , которое в seq_(n) функции передаётся.

Результаты

seq_range seq_random

Рисунки подтверждают, что sorted_insertion() показывает линейное поведение на отсортированном вводе ( seq_range =0,1,2,3,4. n-1 ). И квадратичное на случайном вводе ( seq_random ). Коэффициент перед log2(N) показывает приближённо соответствующую степень в функции роста алгоритма в зависимости от размера ввода:

|------------------------------+-------------------| | Fitting polynom | Function | |------------------------------+-------------------| | 1.00 log2(N) + 1.25e-015 | N | | 2.00 log2(N) + 5.31e-018 | N*N | | 1.19 log2(N) + 1.116 | N*log2(N) | | 1.37 log2(N) + 2.232 | N*log2(N)*log2(N) | 

reporttime + pandas

Собрав результаты измерений времени выполнения функций сортировки из daedra.py ( sorted_*() ) для разных типов (уже отсортированный/случайный) и размеров ввода (длины от 1 до 100000):

import random import daedra from reporttime import get_functions_with_prefix, measure_func times = <> # (function name, input type, exp size) -> time it takes for f in get_functions_with_prefix('sorted_', module=daedra): for N in range(6): for case, L in [ ("range", list(range(10**N))), ("random", list(range(10**N)))]: if case == "random": random.shuffle(L) times[(f.__name__, case, N)] = measure_func(f, [L]) 

Удобно исследовать результаты интерактивно, используя pandas.DataFrame :

import pandas as pd df = pd.DataFrame([dict(function=f, input=i, size=10**n, time=t) for (f,i,n), t in times.items()]) 

К примеру, чтобы сравнить поведение функций на уже отсортированном вводе:

def plot_input(input): p = df[df.input==input].pivot(index='function', columns='size', values='time') p.T.plot(loglog=True, style='-o', title=input) # same style as in @MaxU's answer return p plot_input('range') 

range input

Поведение на случайном вводе:

random input

Или сравнить поведение одной функции для разных типов ввода на одном графике:

p = df[df.function=='sorted_insertion'].pivot(index='input', columns='size', values='time') p.T.plot(loglog=True, style='-o', title='sorted_insertion') 

Источник

Как измерить время выполнения функции в Python

Как измерить время выполнения функции в Python

Оптимизация и профилирование кода требуют от программистов умения измерять время выполнения отдельных функций. Это помогает выявить узкие места в коде и делает оптимизацию более целенаправленной. В этой статье мы рассмотрим различные подходы к измерению времени выполнения функции в Python.

Использование модуля time

Одним из наиболее прямых способов измерить время выполнения функции в Python является использование модуля time . Приведем пример его использования:

import time def my_func(): for _ in range(1000000): pass start_time = time.time() my_func() end_time = time.time() print(f"Функция выполнилась за секунд.")

Функция time.time() возвращает текущее время в секундах, прошедшее с начала эпохи (обычно это 00:00 1 января 1970 года).

Использование функции time.perf_counter

Функция time.perf_counter() представляет собой более точную альтернативу time.time() . Она измеряет время с максимально возможной точностью для вашей платформы.

import time def my_func(): for _ in range(1000000): pass start_time = time.perf_counter() my_func() end_time = time.perf_counter() print(f"Функция выполнилась за секунд.")

Использование функции time.process_time

Функция time.process_time() измеряет время процессора, вместо реального времени. Это может быть полезно для измерения времени выполнения функции, которое не зависит от других процессов в системе.

import time def my_func(): for _ in range(1000000): pass start_time = time.process_time() my_func() end_time = time.process_time() print(f"Функция выполнилась за секунд.")

Использование модуля timeit

Модуль timeit в Python предоставляет мощный и гибкий способ измерения времени выполнения небольших фрагментов кода. Он предназначен для избежания некоторых общих ловушек при измерении времени выполнения.

import timeit def my_func(): for _ in range(1000000): pass execution_time = timeit.timeit(my_func, number=1000) print(f"Функция выполнилась за секунд.")

Функция timeit.timeit() принимает два аргумента: функцию для выполнения и количество раз, которое нужно выполнить эту функцию.

Использование декораторов для измерения времени выполнения

Иногда может быть полезно создать декоратор для измерения времени выполнения функции. Это особенно полезно, если вам нужно измерить время выполнения многих функций.

import time def timer_decorator(func): def wrapper(*args, **kwargs): start_time = time.perf_counter() result = func(*args, **kwargs) end_time = time.perf_counter() print(f"Функция выполнилась за секунд.") return result return wrapper @timer_decorator def my_func(): for _ in range(1000000): pass my_func()

Заключение

Измерение времени выполнения функции в Python — важный навык для любого разработчика. Будь то простое использование модуля time , использование функций с большей точностью, таких как time.perf_counter() , или более сложные инструменты, такие как модуль timeit и декораторы, Python предлагает множество вариантов для решения этой задачи. Использование этих инструментов может помочь вам сделать ваш код более эффективным и быстрым.

Работа с исключениями в Python: try, except, else, finally и raise

Работа с исключениями в Python: try, except, else, finally и raise

Преобразование строки в список в Python: лучшие способы и практические примеры

Преобразование строки в список в Python: лучшие способы и практические примеры

Как использовать логические операторы and, or и not в Python — разбираем на примерах

Как использовать логические операторы and, or и not в Python — разбираем на примерах

Как найти максимальный элемент в списке Python: основные способы

Как найти максимальный элемент в списке Python: основные способы

Методы index() и rindex() в Python: синтаксис, описание и примеры

Методы index() и rindex() в Python: синтаксис, описание и примеры

Использование isupper() в Python: распознавание символов в верхнем регистре с примерами и синтаксисом

Использование isupper() в Python: распознавание символов в верхнем регистре с примерами и синтаксисом

Источник

Оцените статью