[英]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
使用sum , operator和itertools将消除几乎所有纯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.