0

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

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

4 回答 4

5

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

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

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

通常,如果您有数千个数字的列表,则使用 numpy 数组可能会带来重大的性能提升。

于 2012-09-11T04:43:07.090 回答
3

这看起来像是itertools 模块的工作:

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

使用sumoperatoritertools将消除几乎所有纯 python 开销。

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

信用:罗伯特·金(Robert King)在必要时减去最后一个平方的想法。

另一个注意事项,如果您有兴趣获得高精度(即最小化精度损失),请考虑使用math.fsum而不是sum

于 2012-09-11T04:45:22.923 回答
2

这是我能找到的最快的

from itertools import imap
from operator import mul
def sumsquared(arr):
    return sum(imap(mul, arr, arr))
于 2012-09-11T05:21:06.870 回答
1
sum([i**2 for i in arr]) - (arr[-1]**2 if len(arr) % 2 else 0)
于 2012-09-11T04:56:06.267 回答