Измерьте время функции с аргументами в Python

Пытаюсь измерить время raw_queries(...), пока безуспешно. Я обнаружил, что мне следует использовать модуль timeit. Проблема в том, что я не могу (= не знаю как) передать аргументы функции из окружения.

Важное примечание: перед вызовом raw_queries мы должны выполнить phase2() (инициализация среды).

Боковое примечание: код находится на Python 3.

def raw_queries(queries, nlp):
    """ Submit queries without getting visual response """

    for q in queries:
        nlp.query(q)

def evaluate_queries(queries, nlp):
    """ Measure the time that the queries need to return their results """

    t = Timer("raw_queries(queries, nlp)", "?????")
    print(t.timeit())

def phase2():
    """ Load dictionary to memory and subsequently submit queries """

    # prepare Linguistic Processor to submit it the queries
    all_files = get_files()
    b = LinguisticProcessor(all_files)
    b.loadDictionary()

    # load the queries
    queries_file = 'queries.txt'
    queries = load_queries(queries_file)

if __name__ == '__main__':
    phase2()

Спасибо за любую помощь.

ОБНОВЛЕНИЕ: мы можем вызвать phase2(), используя второй аргумент Timer. Проблема в том, что нам нужны (queries, nlp) аргументы из окружения.

ОБНОВЛЕНИЕ: лучшее решение на данный момент с помощью unutbu (только то, что изменилось):

def evaluate_queries():
    """ Measure the time that the queries need to return their results """

    t = Timer("main.raw_queries(queries, nlp)", "import main;\
        (queries,nlp)=main.phase2()")

    sf = 'Execution time: {} ms'
    print(sf.format(t.timeit(number=1000)))


def phase2():
    ...

    return queries, b


def main():
    evaluate_queries()

if __name__ == '__main__':
    main()

person Dimitris Leventeas    schedule 27.12.2009    source источник


Ответы (5)


Во-первых, никогда не используйте модуль времени для измерения времени. Это легко может привести к неверным выводам. См. Пример timeit по сравнению с декоратором времени.

Самый простой способ задать время для вызова функции - использовать команду IPython% timeit. Там вы просто запускаете интерактивный сеанс IPython, вызываете phase2(), определяете queries, а затем запускаете

%timeit raw_queries(queries,nlp)

Второй самый простой способ, который я знаю использовать timeit, - это вызвать его из командной строки:

python -mtimeit -s"import test; queries=test.phase2()" "test.raw_queries(queries)"

(В приведенной выше команде я предполагаю, что сценарий называется test.py)

Идиома здесь

python -mtimeit -s"SETUP_COMMANDS" "COMMAND_TO_BE_TIMED"

Чтобы передать queries вызову функции raw_queries, необходимо определить переменную queries. В опубликованном вами коде queries определено в phase2(), но только локально. Итак, чтобы установить queries в качестве глобальной переменной, вам нужно сделать что-то вроде have phase2 return queries:

def phase2():
    ...
    return queries

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

def phase3():
    # Do stuff like phase2() but return queries
    return queries
person unutbu    schedule 27.12.2009
comment
Спасибо! Это сработало прекрасно: python3 -mtimeit -simport main; (запросы, b) = main.phase2 () main.raw_queries (запросы, b) - person Dimitris Leventeas; 27.12.2009

Решением может быть функция настраиваемого таймера:

import time

def timer(fun,*args):
    start = time.time()
    ret = fun(*args)
    end = time.time()
    return (ret, end-start)

Используя вот так:

>>> from math import sin
>>> timer(sin, 0.5)
(0.47942553860420301, 6.9141387939453125e-06)

Это означает, что sin вернул 0.479..., и это заняло 6.9e-6 секунд. Убедитесь, что ваши функции работают достаточно долго, если вы хотите получить надежные числа (не как в примере выше).

person sastanin    schedule 27.12.2009
comment
Спасибо за ответ. К сожалению, это не тот случай. raw_query должен работать в очень короткие сроки. Мы могли бы решить эту проблему, используя цикл, но официальная документация настоятельно рекомендует использовать timeit по некоторым причинам. - person Dimitris Leventeas; 27.12.2009
comment
О, использование `fun (* args) для обработки вызова аргументов довольно умно. - person WestCoastProjects; 08.06.2019

Обычно вы используете timeit.

Примеры приведены здесь и здесь.

Также обратите внимание:

По умолчанию timeit () временно отключает сборку мусора на время. Преимущество этого подхода в том, что независимые тайминги становятся более сопоставимыми. Этот недостаток заключается в том, что сборщик мусора может быть важным компонентом производительности измеряемой функции.

Или вы можете написать свой собственный таймер, используя модуль time.

Если вы используете собственный таймер, помните, что вы должны использовать time.clock () для Windows и time.time () на других платформах. (время выбирает внутренне)

import sys
import time

# choose timer to use
if sys.platform.startswith('win'):
    default_timer = time.clock
else:
    default_timer = time.time

start = default_timer()
# do something
finish = default_timer()
elapsed = (finish - start)
person Corey Goldberg    schedule 27.12.2009
comment
Спасибо, Кори (кстати, я слежу за тобой в твиттере (тускло)). Я бы предпочел использовать модуль timeit, но я нигде не могу найти пример подобной ситуации, как та, с которой я имею дело (что я считаю довольно частым случаем). - person Dimitris Leventeas; 27.12.2009
comment
myle, я только что добавил ссылку на diveintopython.org/performance_tuning/timeit.html помогает ? - person Corey Goldberg; 27.12.2009
comment
Уже прочитав это. Это мало помогло (как передать аргументы или как инициализировать среду?) Timeit создает новую изолированную среду. - person Dimitris Leventeas; 27.12.2009

Я не уверен в этом, я никогда не использовал его, но из того, что я читал, должно быть что-то вроде этого:

....
t = Timer("raw_queries(queries, nlp)", "from __main__ import raw_queries")
print t.timeit()

Я взял это из http://docs.python.org/library/timeit.html (если это поможет).

person Alex Ntousias    schedule 27.12.2009
comment
Я уже пробовал. Это не работает, потому что запросы и nlp не находятся в среде выполнения. Я использую Python3, если это имеет значение. Также имейте в виду, что я должен вызвать phase2 () перед измерением времени raw_queries (). Спасибо за ответ. - person Dimitris Leventeas; 27.12.2009

Вы так не говорите, но вы случайно не пытаетесь заставить код работать быстрее? Если это так, я предлагаю вам не сосредотачиваться на конкретном распорядке и попытаться рассчитать его по времени. Даже если вы получите номер, он не скажет вам, что исправить. Если вы можете приостановить программу в среде IDE несколько раз и изучить ее состояние, включая стек вызовов, она расскажет вам, на что уходит время и почему. Вот ссылка, которая дает краткое объяснение того, как и почему это работает. *

* При переходе по ссылке возможно придется перейти в конец предыдущей страницы ответов. У SO возникли проблемы с переходом по ссылке на ответ.

person Mike Dunlavey    schedule 28.12.2009
comment
Спасибо, Майк за ваше предложение. Ваша догадка верна. Я пытался оптимизировать raw_queries. Вот почему я сконцентрировался на этом. Я уверен, что мне следует сосредоточиться именно на этом. - person Dimitris Leventeas; 29.12.2009
comment
@myle: Что ж, я пытался предположить, что у вас может быть предположение, что проблема в raw_queries, но вы должны отложить это предположение, потому что образцы стека скажут вам, где проблема есть, и вы должны верить им, независимо от вашего предварительного предположения (которое может быть или не может быть тем, что вам нужно исправить). - person Mike Dunlavey; 29.12.2009
comment
Я понимаю вашу точку зрения. Другими словами, вы предлагаете использовать профилировщик перед оптимизацией. Ваша точка зрения верна. Но в данном случае меня интересуют только raw_queries из-за характера проекта. На этом построен весь проект (я создавал что-то вроде небольшой поисковой системы для образовательных целей, а запросы - это некоторые поисковые запросы). - person Dimitris Leventeas; 29.12.2009
comment
@myle: Даже в этом случае возьмите образцы стека. Если вы правы, они вам скажут. Если ваше беспокойство неуместно, они вам скажут. Если вы правы насчет raw_queries, они скажут вам почему и скажут, что нужно исправить, чтобы сделать это быстрее. Простое измерение времени дает вам число, но если ваша цель - уменьшить это число, вам нужно что-то, что подскажет, что исправить. Вот что делают образцы стека. Если вам трудно понять эту концепцию, вы не одиноки. - person Mike Dunlavey; 29.12.2009