是什么导致这些方法调用时间的巨大差异?

时间:2011-02-08 00:55:11

标签: python

从这里使用接受的答案(带有doctests)给Memoized装饰器:What can be done to speed up this memoization decorator?

和以下代码(fib.py):

class O(object):

  def nfib(self,n): # non-memoized fib fn

     if n in (0, 1):
        return n
     return self.nfib(n-1) + self.nfib(n-2)

  @Memoized
  def fib(self,n): # memoized fib fn

     if n in (0, 1):
        return n
     return self.fib(n-1) + self.fib(n-2)


if __name__ == '__main__':
  import time
  o = O()

  stime = time.time()
  print "starting non-memoized"
  for i in range(10):
    print o.nfib(32)
  print "finished non-memoized - elapsed secs =", time.time() - stime

  stime = time.time()
  print "starting memoized"
  for i in range(10):
    print o.fib(32)
  print "finished memoized - elapsed secs =", time.time() - stime

  stime = time.time()
  print "starting memoized with reset"
  for i in range(10):
    Memoized.reset()
    print o.fib(32)
  print "finished memoized with reset - elapsed secs =", time.time() - stime

我得到以下输出:

C:\TEMP>python fib.py
starting non-memoized
2178309
2178309
2178309
2178309
2178309
2178309
2178309
2178309
2178309
2178309
finished non-memoized - elapsed secs = 16.4189999104
starting memoized
2178309
2178309
2178309
2178309
2178309
2178309
2178309
2178309
2178309
2178309
finished memoized - elapsed secs = 0.00100016593933
starting memoized with reset
2178309
2178309
2178309
2178309
2178309
2178309
2178309
2178309
2178309
2178309
finished memoized with reset - elapsed secs = 0.00299978256226

C:\TEMP>

我原本期望第三个循环和第一个循环一样长,因为它每次循环都会重置它的缓存。将调试语句插入到fib方法中会显示它没有被缓存,并且确实在第三个循环中计算结果,但它比第一个循环大得多。为什么???

我希望我忽略了一些令人尴尬的事情,但我的好奇心目前超过了我的骄傲。 (b.t.w。我在Windows 7专业机器上使用64位python 2.7,如果重要的话)

感谢。

3 个答案:

答案 0 :(得分:6)

天真斐波纳契函数的调用树不是线性或三角形,而是多维金字塔形。通过记忆甚至一次你从树中调整大量的调用量,将金字塔变成一个大多数线性结构。

答案 1 :(得分:3)

第三个循环在计算每个最终结果后重置 - 但是,它仍然受益于递归调用的记忆。

答案 2 :(得分:1)

time.time()不应该用于时间码,特别是在Windows上!使用timeit module。这是一个旧intoduction。一个大问题是计算机不断地做数百件事。如果Outlook正在提取电子邮件时运行一部分,则可能需要稍长于Outlook完成后的其他功能。重复任务并采取最小化往往会更好。这个以及许多其他内容由timeit模块自动处理。

关于Windows,这部分非常相关:

  

在Windows上,time.clock()具有微秒粒度但是   time.time()的粒度是1/60秒