【问题标题】:Measure time of a function with arguments in Python在 Python 中测量带参数的函数的时间
【发布时间】:2010-12-30 07:40:33
【问题描述】:

我正在尝试测量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()

感谢您的帮助。

更新:我们可以使用Timer 的第二个参数调用phase2()。问题是我们需要来自环境的参数(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()

【问题讨论】:

    标签: python performance time arguments timeit


    【解决方案1】:

    对此我不确定,我从未使用过它,但根据我的阅读,它应该是这样的:

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

    我从http://docs.python.org/library/timeit.html 那里得到这个(如果有帮助的话)。

    【讨论】:

    • 我已经试过了。它不起作用,因为查询和 nlp 不在执行环境中。如果这有什么不同,我会使用 Python3。另外,请注意,在测量 raw_queries() 的时间之前,我必须调用 phase2()。感谢您的回复。
    【解决方案2】:

    自定义计时器功能可能是一个解决方案:

    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 秒。如果您想获得可靠的数字,请确保您的函数运行时间足够长(不像上面的示例)。

    【讨论】:

    • 感谢您的回复。不幸的是,这种情况并非如此。 raw_query 应该在很短的时间内运行。我们可以通过使用循环来解决这个问题,但出于某些原因,官方文档强烈建议使用 timeit。
    • 哦,使用 `fun(*args) 处理参数调用非常聪明。
    【解决方案3】:

    通常,您会使用timeit

    例如herehere

    另请注意:

    默认情况下timeit()会临时转 期间关闭垃圾收集 定时。这种方法的优点 是它独立计时 更具可比性。这个缺点是 GC可能是一个重要的组成部分 功能的表现 正在测量

    或者您可以使用time 模块编写自己的自定义计时器。

    如果您使用自定义计时器,请记住您应该在 Windows 上使用 time.clock(),在其他平台上使用 time.time()。 (timeit 内部选择)

    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)
    

    【讨论】:

    • 感谢 corey(顺便说一句,我在 twitter 上关注你(dimle))。我更喜欢使用 timeit 模块,但我在任何地方都找不到与我正在处理的情况类似的示例(我发现这是一个很常见的情况)。
    • myle,我刚刚添加了一个指向 diveintopython.org/performance_tuning/timeit.html 的链接,这有帮助吗?
    • 已经读过了。它没有提供足够的帮助(如何传递参数或如何初始化环境?) timeit 创建了一个新的隔离环境。
    【解决方案4】:

    首先,永远不要使用时间模块来计时功能。它很容易导致错误的结论。示例见timeit versus timing decorator

    对函数调用计时的最简单方法是使用 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 设置为全局变量,您需要执行一些操作,例如让phase2 返回queries

    def phase2():
        ...
        return queries
    

    如果你不想这样搞砸phase2,请创建一个虚拟函数:

    def phase3():
        # Do stuff like phase2() but return queries
        return queries
    

    【讨论】:

    • 谢谢!这就像一个魅力:python3 -mtimeit -s"import main; (queries,b)=main.phase2()" "main.raw_queries(queries,b)"
    【解决方案5】:

    您没有这么说,但您是否有机会尝试让代码运行得更快?如果是这样,我建议您不要专注于特定的例程并尝试对其进行计时。即使你得到一个数字,它也不会真正告诉你要修复什么。如果您可以在 IDE 下多次暂停程序并检查它的状态,包括调用堆栈,它会告诉您什么花费了时间以及为什么。 Here is a link that gives a brief explanation of how and why it works.*

    *当您点击链接时,您可能需要转到上一页答案的底部。 SO 在点击答案链接时遇到问题。

    【讨论】:

    • 感谢迈克的建议。你的猜测是真的。我试图优化 raw_queries。这就是我专注于它的原因。我很肯定这是我应该专注的地方。
    • @myle:嗯,我想建议的是,你可能会猜测 raw_queries 是问题所在,但你应该把这个猜测放在一边,因为堆栈样本会告诉您问题出在哪里,您应该相信它们,无论您之前的猜测如何(这可能或可能不是是您需要解决的问题)。
    • 我明白你的意思。换句话说,您建议在优化之前使用分析器。你的观点是有效的。但在这种情况下,由于项目的性质,我只对 raw_queries 感兴趣。整个项目都是围绕它构建的(我正在构建一个用于教育目的的小型搜索引擎,查询是一些查找)。
    • @myle:即便如此,还是采集堆栈样本。如果你是对的,他们会告诉你的。如果您的担忧放错了地方,他们会告诉您。如果您对 raw_queries 的看法是正确的,他们会告诉您为什么,并且他们会告诉您如何解决以使其更快。仅仅测量时间会给你一个数字,但如果你的目标是减少这个数字,你需要一些东西来告诉你要解决的问题。这就是堆栈样本的作用。如果您觉得这个概念难以掌握,那么您并不孤单。
    猜你喜欢
    • 2016-06-24
    • 2011-07-25
    • 1970-01-01
    • 2023-03-31
    • 2010-12-13
    • 2014-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多