这是一个开始。首先,对于任何错误,我深表歉意。
我尝试了几种不同的方法。我对总和的限制有点困惑 - 上限应该是i, 而不是i−1?
编辑:不,问题中提供的上限是正确的。我把它留在这里是因为另一个答案现在使用相同的代码,但修复很简单。
首先是循环版本:
def looped_ver(k, a):
x = np.empty_like(a)
for i in range(x.size):
sm = 0
for j in range(0, i+1):
sm += k[i-j,j] * a[i-j] * a[j]
x[i] = sm
return x
我用 numpy 切片使它成为一个循环:
def vectorized_ver(k, a):
ktr = zeros_like(k)
ar = zeros_like(k)
sz = len(a)
for i in range(sz):
ktr[i,:i+1] = k[::-1].diagonal(-sz+i+1)
a_ = a[:i+1]
ar[i,:i+1] = a_[::-1] * a_
return np.sum(ktr * ar, 1)
带有一个显式循环的 numpy 版本在我的计算机上大约快 25 倍n=5000.
然后我写了一个 Cython 版本的(更易读的)循环代码。
import numpy as np
import cython
cimport numpy as np
@cython.boundscheck(False)
@cython.wraparound(False)
def cyth_ver(double [:, ::1] k not None,
double [:] a not None):
cdef double[:] x = np.empty_like(a)
cdef double sm
cdef int i, j
for i in range(len(a)):
sm = 0.0
for j in range(i+1):
sm = sm + k[i-j,j] * a[i-j] * a[j]
x[i] = sm
return x
在我的笔记本电脑上,这个比循环版本快 200 倍(比 1 循环矢量化版本快 8 倍)。我相信其他人可以做得更好。
我玩的是 Julia 版本,它似乎(如果我计时正确的话)与 Cython 代码相当。