Мы можем объединить A
с одним собственным срезом, а затем получить эти скользящие окна.Чтобы получить эти окна, мы можем использовать np.lib.stride_tricks.as_strided
на основе scikit-image's view_as_windows
.Затем умножьте эти окна на B
для окончательного вывода. Больше информации об использовании as_strided
на основе view_as_windows
.
Следовательно, у нас будет одно векторизованное решение, например, так:
In [70]: from skimage.util.shape import view_as_windows
In [71]: A1 = np.concatenate((A,A[:,:-1]),axis=1)
In [74]: view_as_windows(A1,A.shape)[0]*B
Out[74]:
array([[[1, 0, 3],
[0, 0, 6]],
[[2, 0, 1],
[0, 0, 4]],
[[3, 0, 2],
[0, 0, 5]]])
Мы также можем использовать multi-cores
с numexpr
module для последнего шага broadcasted-multiplication
, который должен быть лучше на больших массивах.Следовательно, для примера, это было бы -
In [53]: import numexpr as ne
In [54]: w = view_as_windows(A1,A.shape)[0]
In [55]: ne.evaluate('w*B')
Out[55]:
array([[[1, 0, 3],
[0, 0, 6]],
[[2, 0, 1],
[0, 0, 4]],
[[3, 0, 2],
[0, 0, 5]]])
Синхронизация на больших массивах, сравнивая предложенные два метода -
In [56]: A = np.random.rand(500,500)
...: B = np.random.rand(500,500)
In [57]: A1 = np.concatenate((A,A[:,:-1]),axis=1)
...: w = view_as_windows(A1,A.shape)[0]
In [58]: %timeit w*B
...: %timeit ne.evaluate('w*B')
1 loop, best of 3: 422 ms per loop
1 loop, best of 3: 228 ms per loop
Выжимая лучшееметод на основе шага
Если вы действительно выжмете лучшее из подхода на основе шага, используйте исходный метод np.lib.stride_tricks.as_strided
, чтобы избежать перегрузки в работеview_as_windows
-
def vaw_with_as_strided(A,B):
A1 = np.concatenate((A,A[:,:-1]),axis=1)
s0,s1 = A1.strides
S = (A.shape[1],)+A.shape
w = np.lib.stride_tricks.as_strided(A1,shape=S,strides=(s1,s0,s1))
return w*B
По сравнению с базирующимся на @Paul Panzer's array-assignment
кроссовер выглядит как массивы 19x19
-
In [33]: n = 18
...: A = np.random.rand(n,n)
...: B = np.random.rand(n,n)
In [34]: %timeit vaw_with_as_strided(A,B)
...: %timeit pp(A,B)
10000 loops, best of 3: 22.4 µs per loop
10000 loops, best of 3: 21.4 µs per loop
In [35]: n = 19
...: A = np.random.rand(n,n)
...: B = np.random.rand(n,n)
In [36]: %timeit vaw_with_as_strided(A,B)
...: %timeit pp(A,B)
10000 loops, best of 3: 24.5 µs per loop
10000 loops, best of 3: 24.5 µs per loop
Итак,для чего-то меньшего, чем 19x19
, array-assignment
кажется лучше, а для более крупного, чем пошаговое, должен быть путь.