繁体   English   中英

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

[英]Optimising a simple mathematical calculation over list

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

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%。 有什么办法可以加快功能的运行速度吗?

您的功能很奇怪。 它所做的只是计算元素的平方和,不同之处在于,如果存在奇数个元素,它将丢弃最后一个元素。 您出于某种原因一次添加两个,但这并不影响最终结果。

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

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

通常,如果您有成千上万个数字的列表,那么使用numpy数组可能会带来很大的性能提升。

这看起来像是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

这是我能找到的最快的

from itertools import imap
from operator import mul
def sumsquared(arr):
    return sum(imap(mul, arr, arr))
sum([i**2 for i in arr]) - (arr[-1]**2 if len(arr) % 2 else 0)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM