Используйте delimiter.c_str()
как разделитель :
copy(x.begin(),x.end(), ostream_iterator(s,delimiter.c_str()));
Таким образом, вы получаете const char*
, указывающие на строку, что ostream_operator
ожидает от ваш std::string
.
Работа 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
Обратите внимание, что серия операторов делает новую копию несортированных данных на каждом проходе.
Также обратите внимание на методику синхронизации запуска набора измерений семь раз и сохранение только наилучшего времени - это может действительно помочь уменьшить искажения измерений из-за к другим процессам, запущенным в вашей системе.
Это мои советы по правильному использованию timeit. Надеюсь, это поможет: -)
Встроенный модуль timeit лучше всего работает с командной строкой 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
# Генерация целых чисел
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)"
для меня это самый быстрый способ:
import timeit
def foo():
print("here is my code to time...")
timeit.timeit(stmt=foo, number=1234567)
позволяет установить один и тот же словарь в каждом из следующих и проверить время выполнения.
Аргумент настройки в основном настраивает словарь
. Номер предназначен для запуска кода 1000000 раз , Не настройка, а stmt
Когда вы запустите это, вы увидите, что индекс быстрее, чем get. Вы можете запустить его несколько раз, чтобы увидеть.
Код в основном пытается получить значение 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
по get: 0.54841166886888
Если вы хотите использовать timeit
в интерактивном сеансе Python, есть два удобных варианта:
%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
. Я не думаю, что это так широко известно, как должно быть. Это полезно в таких случаях, когда вызывается функция или вызов метода. В других случаях (временная последовательность шагов) он менее полезен, поскольку он вводит служебные вызовы функций.
– Raymond Hettinger
22 November 2011 в 04:30
sys._getframe(N).f_globals
) должны были быть по умолчанию с самого начала.
– kxr
6 May 2017 в 08:15
просто передайте весь код в качестве аргумента timeit:
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))
Я нахожу, что самый простой способ использовать timeit - из командной строки:
Учитывая test.py:
def InsertionSort(): ...
def TimSort(): ...
run timeit как это:
% python -mtimeit -s'import test' 'test.InsertionSort()'
% python -mtimeit -s'import test' 'test.TimSort()'
Я расскажу вам о секрете: лучший способ использовать timeit
находится в командной строке.
В командной строке timeit
выполняет правильный статистический анализ: он сообщает вам как долго длился самый короткий пробег. Это хорошо, потому что ошибка во времени положительна. Таким образом, самое короткое время имеет наименьшую ошибку. Невозможно получить отрицательную ошибку, потому что компьютер никогда не может вычислить быстрее, чем он может вычислить!
Итак, интерфейс командной строки:
%~> python -m timeit "1 + 2"
10000000 loops, best of 3: 0.0468 usec per loop
Это довольно просто, eh?
Вы можете настроить файл:
%~> 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
внутри скрипта Python. Я предлагаю избегать этого, потому что анализ и синхронизация просто лучше в командной строке. Вместо этого я стараюсь создавать сценарии оболочки:
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)
, и это дает вам кумулятивное ( not минимум!) время для запуска этого количества раз.
Чтобы получить хороший анализ, используйте .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 мкс. Вы только знаете, что это меньше , чем это. Вся ошибка положительная. Поэтому попробуйте найти чистые накладные расходы: >>> 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
Обратите внимание, что вычитание служебных данных здесь разумно только потому, что накладные расходы являются малой частью времени. Для вашего примера стоит отметить, что и Sorting Sort и Tim Sort имеют совершенно необычное временное поведение для уже отсортированных списков. Это означает, что вам понадобится random.shuffle
между сортировками, если вы хотите избежать разрушения ваших таймингов. Пример использования интерпретатора Python REPL с функцией, которая принимает параметры.
>>> 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
Если вы хотите быстро сравнить два блока кода / функций, вы можете сделать:
import timeit
start_time = timeit.default_timer()
func1()
print(timeit.default_timer() - start_time)
start_time = timeit.default_timer()
func2()
print(timeit.default_timer() - start_time)
a=s[:]
? Что бы вы сделали, если бы хотели получить чисто время сортировки? – max 6 February 2012 в 10:33timsort(a)
и возьмите разницу :-) – Raymond Hettinger 7 February 2012 в 03:58.repeat(7,1000)
уже делает это (используя одно и то же семя)! Таким образом, ваше решение идеально подходит IMO. – max 3 April 2012 в 22:04.repeat(7, 1000)
vs..repeat(2, 3500)
vs.repeat(35, 200
), должно зависеть от того, как ошибка из-за загрузки системы сравнивается с ошибкой из-за изменчивости ввода. В крайнем случае, если ваша система всегда находится под большой нагрузкой, и вы видите длинный тонкий хвост слева от распределения времени выполнения (когда вы его поймаете в редком состоянии бездействия), вы даже можете найти.repeat(7000,1)
более полезным чем.repeat(7,1000)
, если вы не можете заплатить более 7000 прогонов. – max 3 April 2012 в 22:19