2013-06-18 20 views
1

我想优化一些代码,所以我想我会仔细研究我的瓶颈在哪里。我有四个功能,包装eachother如:为什么嵌套时函数的速度测试不会添加? (Python)

return f1(f2(f3(f4()))) 

所以我测试每个单独以及整体。当单独地我基本上预先计算了以前的功能。但是,我认为他们会加起来总的时间。但他们没有,在我结合他们时,它显着增长。所以我决定以较小的比例来看待它。我写了这个测试

def f1(): 
    return 2 

def f2(num): 
    return num*num 

def test(): 
    for i in range(1000000): 
     f1() 
def test2(): 
    for i in range(1000000): 
     f2(2) 
def test3(): 
    for i in range(1000000): 
     f2(f1()) 

我回到测试为0.085秒,TEST2作为0.125秒和TEST3作为0.171秒。这使我困惑于两种方式。 1)为什么不测试3.21秒,和2)为什么它缩短了,而不是我的问题变得更长?

+0

这些结果有多可重复性? – recursive

+0

你怎么测试时间(出于好奇)? –

+0

@递归,它们总是相同的,经过多次测试。 –

回答

2

既然你没有给我们重现原来的问题代码,这是很难做到的任何事情,但想......但我可以在这里做一些猜测。


当您撰写两个非常小的功能,更多的时候,你运行它,你就越有可能是有字节码两种功能,在全局和当地人词典等等都在你的缓存。另一方面,当你编写两个非常大的函数时,每次内部函数运行时,你很可能会将外部函数的一部分从缓存中移出,所以你最终会花费更多时间在缓存补充上,而不是实际解释你的代码。


最重要的是,你忘记了调用函数的代价。在Python中,这不仅仅是一个函数调用 - 你通常通过全局名称调用函数,并且LOAD_GLOBAL可能非常慢。这样如果你写的玩具组成:

def test3(): 
    for i in range(1000000): 
     f2(f1()) 

...你不付出代价的查找尽可能多,如果你这样做:

def f2(): 
    return 2 * f1() 
def test3(): 
    for i in range(1000000): 
     f2() 

...但你可以支付几乎没有为它通过将f1复制到适当的locals中。对于上面的两个例子:

def test3(): 
    _f1 = f1 
    for i in range(1000000): 
     f2(_f1()) 

def f2(_f1=f1): 
    return 2 * _f1() 
def test3(): 
    for i in range(1000000): 
     f2() 

你的测试功能包括你什么时间安装成本。

例如,如果您使用的是Python 2.x,则range(1000000)可能占用总时间的很大一部分时间。但test1 + test2只做了两次,而test3只做了一次。所以,在玩具测试中,test3的节省足以引起注意是非常合理的。但是在你的真实测试中,每个循环需要比如说100倍的延长,range调用的成本是微不足道的。

另外值得一提的是,如果你创建了足够的内存,你可以最终触发malloc电话甚至VM交换 - 这分别是缓慢和头脑麻木缓慢,这也都更加多变和不可预测的比在循环中运行代码的通常成本。这可能不是一个问题,只是创建和销毁几1M-项目清单(这应该是20-80MB的量级),但它可能


最后,你是如何做的时机还没有告诉我们,你是如何重复测试,你是如何综合这些结果,等等,所以它很可能是你的测试只无效。

+0

感谢您的解释中的细节。不幸的是,其他作品的代码很长,我想不出一个好的方法来压缩它们。 实际的代码确实占用了一些内存,但不应该太大。有没有更好的方法来加以管理?我现在正在经历指数级增长。又如果它们是添加剂,它需要1秒,但我得到4分钟。 :( –

+0

@JeremyThiesen:除非你可以创建一个足够小到后期的例子,重现您的问题,这将是很困难的调试此外,你确定它实际上是指数,而不是线性的,除非有一个悬崖。它在一个非常小的范围内跳跃3个数量级?(后者的行为就是你期望从缓存,虚拟机等问题中得到的结果)。另外,是否有可能做了一些愚蠢的事情,难以发现,你在你的实际代码编写功能的方式是错误的(例如,通过'阵列[我:]',而不是'阵列[我:我+ 1]'到内部功能)? – abarnert

+0

@abarnet我重新设计了一些功能并得到的东西,更像是我的问题。我将不胜感激,如果你接过来一看。http://stackoverflow.com/questions/17199108/running-a-function-withing-another-function-is-faster-than-just -the-function-wh –

3

大量的时间需要列表生成“范围(1000000)”(假设您使用python 2.X)。在test3中,您只创建一次该列表。当你总结时间时,你总结了2次创建列表。

您可以使用分析器知道花费的时间http://docs.python.org/2/library/profile.html

相关问题