优化列表上的简单数学计算

时间:2012-09-11 04:40:45

标签: python optimization

我有一个我正在计算的脚本:

def sumsquared(arr):
    sum = 0
    idx = 0
    len = arr.__len__()
    while idx < (len - 1):
            sum = sum + (arr[idx] * arr[idx]) + (arr[idx+1] * arr[idx+1])
            idx = idx + 2

    return sum

上面的函数在循环中调用,该循环填充两个列表并调用此函数两次:第一次使用len~1024项目列表,第二次使用len~44100项目。根据输入,循环本身可以运行100到100000次。

对于小尺寸输入,基于cProfile的分析通知我:

ncalls  tottime  percall  cumtime  percall  filename:lineno(function)
---------------------------------------------------------------------
 2560   12.065   0.005    12.065    0.005    beat.py:8(sumsquared)

大约是脚本总运行时间的95%。有什么方法可以加快这项功能吗?

4 个答案:

答案 0 :(得分:5)

你的功能很奇怪。它所做的就是计算元素的平方和,除非如果有奇数个元素,它会抛弃最后一个元素。您出于某种原因一次添加两个,但这不会影响最终结果。

为了加快速度,您可以使用numpy而不是编写自己的函数。

>>> x = np.array([1, 2, 3, 4, 5])
>>> sumsquared(x)
30
>>> (x[:2*(len(x)//2)]**2).sum()
30

一般来说,如果你有数千个数字的列表,那么使用numpy数组可能会带来重大的性能提升。

答案 1 :(得分:3)

这看起来像是itertools module

的工作
def sumsquared(arr):
    s = sum(itertools.imap(operator.mul, arr, arr))
    return s - arr[-1] ** 2 if len(arr) & 1 else s

使用 sum 运算符 itertools 将消除几乎所有纯python开销。

此外,当输入为整数,浮点数或两者的某些混合时, sum 已经过优化,以接近C速度运行。它可以累积运行总计,而无需为每个中间小计创建纯python对象。

信用:罗伯特·金在必要时减去最终方格的想法。

另外注意,如果您对获得高准确度(即最小化精度损失)感兴趣,请考虑使用math.fsum代替 sum

答案 2 :(得分:2)

这是我能找到的最快的

from itertools import imap
from operator import mul
def sumsquared(arr):
    return sum(imap(mul, arr, arr))

答案 3 :(得分:1)

sum([i**2 for i in arr]) - (arr[-1]**2 if len(arr) % 2 else 0)