Python - 生成器,迭代器和速度

时间:2012-06-03 20:00:34

标签: python-2.7 generator

[编辑反映了迄今为止的评论,以及我的进一步阅读。]

问题:我很困惑为什么以下三个版本的eta函数,都是用python编写的,都是大约相同的速度,即“绑定”中的线性,以及类似的常量。

作为一点背景:我需要一个相当快速的eta函数版本进行计算。可以找到eta函数的定义here。在给出这三个函数之前,我们需要一个简单的辅助函数。

def chi(n): # Dirichlet character                                                     
    n = n%12
    if n == 1 or n == 11:
        return 1
    if n == 5 or n == 7:
        return -1
    return 0

现在三个版本让我感到困惑。首先,我们有一个明显的单线,直接来自于雅可比θ函数的eta定义。

def eta_Dedekind_theta(tau, bound = 50):
    assert tau.imag > 0
    r = Exp(Pi*I*tau/12)
    # sum_1^infty chi(n) r^(n^2)                                                      
    return sum([chi(n)*r**(n**2) for n in range(1,bound+1)])

其次我们对单行的明显修改:用生成器表达式替换列表理解。

def eta_Dedekind_theta_round(tau, bound = 50):
    assert tau.imag > 0
    r = Exp(Pi*I*tau/12)
    # sum_1^infty chi(n) r^(n^2)                                                      
    return sum((chi(n)*r**(n**2) for n in range(1,bound+1)))

但是这个版本有点 - 为什么用生成器替换列表理解会减慢速度?最后,这是我首先编码的版本。我认为这非常聪明,因为它避免了使用二次方大指数的取幂。

def eta_Dedekind_theta_clever(tau, bound = 50):
    assert tau.imag > 0
    r = Exp(Pi*I*tau/12)
    r2 = r**2
    lin = 1
    quad = r
    sum = 0
    # sum_1^infty chi(n) r^(n^2)                                                      
    for n in range(1, bound+1):
        sum = sum + chi(n)*quad # n^2                                                 
        lin = lin*r2 # 2n                                                             
        quad = quad*lin*r # n^2 + 2n + 1 = (n+1)^2                                    
    return sum

实际上,这个版本比以前的版本都快一点。但我认为这将是线性的,而由于取幂的成本,单行将非常慢。但事实并非如此:时间表明,所有中的都是线性的“绑定”,大致相似的常数。我想我不明白python中的操作成本。

0 个答案:

没有答案