【问题标题】:Serious overhead in Python cProfile?Python cProfile 中的严重开销?
【发布时间】:2011-03-09 06:28:27
【问题描述】:

您好 Python 专家,我开始使用 cProfile 以便获得关于我的程序的更详细的时序信息。但是,让我感到非常不安的是,有很大的开销。知道为什么 cProfile 报告了 7 秒,而时间模块在下面的代码中只报告了 2 秒吗?

# a simple function

def f(a, b):
 c = a+b

# a simple loop
def loop():
 for i in xrange(10000000):
  f(1,2)

# timing using time module
# 2 seconds on my computer
from time import time
x = time()
loop()
y = time()
print 'Time taken %.3f s.' % (y-x)

# timing using cProfile
# 7 seconds on my computer
import cProfile
cProfile.runctx('loop()', globals(), locals())

【问题讨论】:

    标签: python performance time profile cprofile


    【解决方案1】:

    因为它做了更多的工作? time 只是对整个操作进行计时,而 cProfile 在仪器下运行它,因此可以得到详细的细分。显然,分析并不意味着在生产中使用,因此 2.5 倍的开销似乎是一个很小的代价。

    【讨论】:

    • 此外,该功能非常简单,以相对而言,探查器似乎会占用大量的总运行时间。
    • 感谢您的回复。如果我将 loop() 中的迭代次数从 1000 万增加到 10000 万,时间会线性缩放! time 模块用了 20 秒,cProfile 用了 70 秒。我不介意 cProfile 是否需要更长的时间来运行,但报告的时间(即代码中花费的实际时间)应该不包括开销。有没有办法校准 cProfile(因为我只对代码中花费的实际时间感兴趣)?
    • @xqx:我不知道。分析可以让您了解程序不同部分的相对性能,但它不适用于生产性能报告。
    • 谢谢欧文。我不确定我们可以在多大程度上依赖 python 分析器给出的相对性能数字,因为不能保证开销成本是均匀分布的。是否有可能某些函数的开销很大(比如 10 倍),而其他函数的开销微不足道,从而扭曲了结果。我不确定分析包是如何实现的,所以我不知道哪些因素会增加开销。子函数调用的数量绝对是一个因素,正如下面 unutbu 的回复所解释的那样。
    【解决方案2】:

    函数f 很快返回。当您使用 cProfile 时,归因于一次调用 f 的时间是不准确的,因为时间太小以至于与测量时间的误差相当。用于测量时间差异的时钟可能只能精确到 0.001 秒。因此,每次测量的误差可能比您尝试测量的时间大几个数量级。这样做 1e7 次,你就会得到虚假的结果。 (有关此问题的更多讨论,请参阅http://docs.python.org/library/profile.html#limitations。)

    请注意,如果您更改要使用的代码

    def f(a, b):
     for i in xrange(int(1e4)):    
         c = a+b
    
    # a simple loop
    def loop():
     for i in xrange(int(1e3)):
      f(1,2)
    

    你得到

    Time taken 0.732 s.
             1003 function calls in 0.725 CPU seconds
    
       Ordered by: standard name
    
       ncalls  tottime  percall  cumtime  percall filename:lineno(function)
            1    0.000    0.000    0.725    0.725 <string>:1(<module>)
         1000    0.723    0.001    0.723    0.001 test.py:4(f)
            1    0.001    0.001    0.725    0.725 test.py:9(loop)
            1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
    

    您正在执行相同数量的循环,但每次调用 f 需要更长的时间。这减少了每次测量的误差。 (归因于每次调用 f 的时间包含一个错误,现在没有测量到的总时间那么大。)

    【讨论】:

    • 你好,unutbu。在您的示例中,使用和不使用分析器所花费的时间非常接近,即 0.732 秒和 0.725 秒。除了您提到的可能引入的错误之外,我认为在我的示例中,函数 f 被调用了很多次(在您的示例中为 1e7 而不是 1e3),因此具有更多的分析成本。
    猜你喜欢
    • 2011-04-29
    • 2014-02-06
    • 2018-12-25
    • 1970-01-01
    • 1970-01-01
    • 2012-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多