7

我必须做以下类型的许多循环

for i in range(len(a)):
    for j in range(i+1):
        c[i] += a[j]*b[i-j]

其中 a 和 b 是短数组(大小相同,大约在 10 到 50 之间)。这可以使用卷积有效地完成:

import numpy as np
np.convolve(a, b) 

但是,这给了我完整的卷积(即,与上面的 for 循环相比,向量太长了)。如果我在卷积中使用“相同”选项,我会得到中心部分,但我想要的是第一部分。当然,我可以从完整的向量中去掉我不需要的东西,但如果可能的话,我想去掉不必要的计算时间。有人可以建议对循环进行更好的矢量化吗?

4

2 回答 2

3

你可以在 Cython 中编写一个小的 C 扩展:

# cython: boundscheck=False
cimport numpy as np
import numpy as np  # zeros_like

ctypedef np.float64_t np_t
def convolve_cy_np(np.ndarray[np_t] a not None,
                   np.ndarray[np_t] b not None,
                   np.ndarray[np_t] c=None):
    if c is None:
       c = np.zeros_like(a)
    cdef Py_ssize_t i, j, n = c.shape[0]
    with nogil:
        for i in range(n):
            for j in range(i + 1):
                c[i] += a[j] * b[i - j]
    return c

与我的机器n=10..50相比,它表现良好。np.convolve(a,b)[:len(a)]

这似乎也是一份工作numba

于 2012-10-10T14:39:53.327 回答
2

在 numpy 中无法使用矢量化数组操作进行卷积。你最好的选择是使用 np.convolve(a, b, mode='same') 并修剪掉你不需要的东西。这可能比您上面的纯 python 中的双循环快 10 倍。如果你真的关心速度,你也可以用 Cython 自己动手,但它可能不会比 np.convolve() 快多少。

于 2012-10-10T14:06:56.903 回答