【问题标题】:Function call is taking 10 seconds函数调用需要 10 秒
【发布时间】:2015-10-08 00:53:12
【问题描述】:

我使用 cProfile 分析了我的代码以查找瓶颈,我发现了一个特殊的瓶颈。

我的代码结构如下:

def A1Distance(a_list):
    #returns something

pr = cProfile.Profile()
pr.enable()
x = A1Distance(list_comprehension)
pr.disable()

cProfile 总共运行了 17.554 秒。就总时间而言,最重要的函数是:

ncalls  tottime  percall  cumtime  percall filename:lineno(function)

    1    9.884    9.884   17.554   17.554 Cov_Opt_Parallel.py:141(A1Distance)

如您所见,A1Distance 大约需要 10 秒并被调用一次。如果我将 pr.enable() 和 pr.disable() 放在函数内部,则输出相同,但 A1Distance 没有 10 秒。因此,仅调用一个函数似乎需要 10 秒。有什么建议可以解决这个问题吗?

【问题讨论】:

  • A1Distance 是递归函数吗?
  • 您作为参数提供的列表理解执行起来成本高吗?它在函数外部生成,然后传入,因此在函数内部移动分析不会考虑构造 list 的成本。
  • A1Distance 不是递归的。我以前让它做一件事 500 次,但是当我把它减少到 100 次时,函数调用只用了 3.114 秒。当我对它自己进行分析时,列表理解的执行时间显示为 0.000。
  • 我怀疑你在函数内部移动分析时搞砸了。调用一个函数真的不太可能需要 10 秒。而改变函数内部的重复次数改变了时间这一事实意味着成本在函数中,而不是在调用中。
  • 我在函数中重新运行了分析(启用是第一件事,在返回语句之前禁用),我看到了同样的事情。

标签: python function cprofile


【解决方案1】:

您的list_comprehension 需要 10 秒。函数的参数在函数被调用之前被评估,所以如果你在函数内部进行分析,代价高昂的 list_comprehension 已经完成。

例如看这个:

import time, cProfile

def func_a(a_list):
    return len(a_list)

def func_b(a_list, pr):
    pr.enable()
    ret = len(a_list)
    pr.disable()
    return ret


def main():
    pr = cProfile.Profile()
    pr.enable()
    func_a([time.sleep(x) for x in range(3)])
    pr.disable()
    pr.print_stats()

    pr = cProfile.Profile()
    func_b([time.sleep(x) for x in range(3)], pr)
    pr.print_stats()

    pr = cProfile.Profile()
    pr.enable()
    [time.sleep(x) for x in range(3)]
    pr.disable()
    pr.print_stats()

if __name__ == '__main__':
    main()

会输出如下内容:

     7 function calls in 3.006 seconds

Ordered by: standard name

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    1    0.000    0.000    0.000    0.000 tmp.py:3(func_a)
    1    0.000    0.000    0.000    0.000 {len}
    1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
    1    0.000    0.000    0.000    0.000 {range}
    3    3.006    1.002    3.006    1.002 {time.sleep}


     2 function calls in 0.000 seconds

Ordered by: standard name

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    1    0.000    0.000    0.000    0.000 {len}
    1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}


     5 function calls in 3.004 seconds

Ordered by: standard name

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
    1    0.000    0.000    0.000    0.000 {range}
    3    3.004    1.001    3.004    1.001 {time.sleep}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-22
    • 2016-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多