Python 移动Numpy阵列的最快方法

Python 移动Numpy阵列的最快方法,python,arrays,performance,numpy,Python,Arrays,Performance,Numpy,我正在进行一些模拟,包括反复比较2D Numpy数组中的值和它们的“邻居”;例如,将标记位置(y,x)处的值与同一数组中标记位置(y-1,x)处的值进行比较 目前我使用的函数如下: # example of the typical size of the arrays my_array = np.ndarray((500,500)) shapey, shapex = my_array.shape Yshape = (1, shapex) Yzeros = np.zeros((1, sh

我正在进行一些模拟,包括反复比较2D Numpy数组中的值和它们的“邻居”;例如,将标记位置
(y,x)
处的值与同一数组中标记位置
(y-1,x)
处的值进行比较

目前我使用的函数如下:

# example of the typical size of the arrays
my_array = np.ndarray((500,500))    

shapey, shapex = my_array.shape
Yshape = (1, shapex)
Yzeros = np.zeros((1, shapex))

def syf(A, E=True):
    if E == True:
        return np.concatenate((A[1:], A[-1].reshape(Yshape)), axis=0)
    else:
        return np.concatenate((A[1:], Yzeros), axis=0)

shifted_array = syf(my_array)

difference_in_y = shifted_array - my_array 
它可以选择在数组边缘使用边值或零进行比较。这些函数也可以在任意轴的任意方向上执行

有人对更快的方法有什么建议吗? 我尝试了
np.roll
(速度慢得多),这是:

yf = np.ix_(range(shapey)[1:] + [shapey,], range(shapex))
shifted_array = my_array[yf]
稍微慢一点

在一个需要10小时才能运行的程序中,这些函数每秒被调用约200次,因此任何小的加速都更受欢迎

谢谢

编辑:


因此,如果每次调用移位函数时都需要相同的微分方法,那么下面的Divakars方法似乎提供了较小的加速,但是,如果只需要一个移位数组,那么该方法和我上面使用的方法似乎速度相同。

您可以在这样的函数调用中完成移位和微分-

def syf1(A, E=True):
    out = np.empty_like(A)
    out[:-1] = A[1:] - A[:-1] # Or np.diff(my_array,axis=0)
    if E == True:
        out[-1] = 0
    else:
        out[-1] = -A[-1]
    return out
因此,出于运行时比较目的,
syf
的等效修改版本为-

def syf(A, E=True):
    if E == True:
        return np.concatenate((A[1:], A[-1].reshape(Yshape)), axis=0) - A
    else:
        return np.concatenate((A[1:], Yzeros), axis=0) - A
运行时测试

让我们将
syf
的等效版本与问题代码中列出的输入的运行时性能建议方法进行比较-

In [113]: %timeit syf(my_array)
1000 loops, best of 3: 518 µs per loop

In [114]: %timeit syf1(my_array)
1000 loops, best of 3: 494 µs per loop

所以,有一些改进

别忘了,如果E:,你可以做
@马修,谢谢你的提示。我会让它保持现在的状态,因为它确实是一件小事,直到OP带着任何反馈回来。尽管如此,还是要感谢你的建议!感谢Divakar的建议,我尝试了一个稍微不同的实现(我的代码并不总是以这种方式区分,所以只使用了“shift”),这两种方法在速度上基本相同。。。奇怪的是,它们如此相似,我想这只是内存访问时间。@Siyh移位或shift+diff或其他的不同方式?有时它的区别如上所述,但也是>或<比较,找到中间值,添加周围值等。。在x中,移位是向前和向后的。yI建议使用
scipy.ndimage.convalve1d
,但在这种情况下(非常短的过滤器),它实际上比您当前的方法慢约2倍。查看
roll
的代码,它会生成一个与
yf
类似的索引,然后使用
take
。鉴于新数组与旧数组几乎相同,我很惊讶没有一种更快的方法可以通过索引来避免在内存中创建新数组。虽然我猜如果
roll
使用
np.ix
索引,那么可能没有更快的替代方法