use*_*014 7 python optimization numpy matrix python-3.x
我有一个大小为I*J的输入矩阵A.
并且输出矩阵B的大小为N*M.
还有一些预先计算出的大小为N*M*2的地图,它决定了B中的每个坐标,它们在A中进行协调.地图没有我可以使用的特定规则或线性.只是一张似乎随机的地图.
矩阵非常大(~5000*~3000)因此创建映射矩阵是不可能的(5000*3000*5000*3000)
我设法使用简单的地图和循环:
for i in range(N):
for j in range(M):
B[i, j] = A[mapping[i, j, 0], mapping[i, j, 1]]
Run Code Online (Sandbox Code Playgroud)
我设法使用索引来做到这一点:
B[coords_y, coords_x] = A[some_mapping[:, 0], some_mapping[:, 1]]
# Where coords_x, coords_y are defined as all of the coordinates:
# [[0,0],[0,1]..[0,M-1],[1,0],[1,1]...[N-1,M-1]]
Run Code Online (Sandbox Code Playgroud)
这样做效果更好,但仍然有点慢.
我有无限的时间来计算映射或任何其他效用计算.但是在这些预先计算之后,这种映射应该尽可能快地进行.
目前,我看到的唯一其他选择只是在C中重新实现这一点或更快...
(只是为了说清楚是否有人好奇,我用一些编码创建了一些其他形状不同的图像.但是它的'映射非常复杂,并不是简单或线性可以使用的东西)
如果你有无限的时间进行预计算,你可以通过使用平面索引来获得轻微的加速:
map_f = np.ravel_multi_index((*np.moveaxis(mapping, 2, 0),), A.shape)
Run Code Online (Sandbox Code Playgroud)
然后简单地做:
A.ravel()[map_f]
Run Code Online (Sandbox Code Playgroud)
请注意,这种加速是在我们从花式索引中获得的大幅加速之上的。例如:
>>> A = np.random.random((5000, 3000))
>>> mapping = np.random.randint(0, 15000, (5000, 3000, 2)) % [5000, 3000]
>>>
>>> map_f = np.ravel_multi_index((*np.moveaxis(mapping, 2, 0),), A.shape)
>>>
>>> np.all(A.ravel()[map_f] == A[mapping[..., 0], mapping[..., 1]])
True
>>>
>>> timeit('A[mapping[:, :, 0], mappping[:, :, 1]]', globals=globals(), number=10)
4.101239089999581
>>> timeit('A.ravel()[map_f]', globals=globals(), number=10)
2.7831342950012186
Run Code Online (Sandbox Code Playgroud)
如果我们与原始的循环代码进行比较,加速率将更像是 ~40 倍。
最后,请注意,此解决方案不仅避免了额外的依赖项和潜在的 numba 安装噩梦,而且更简单、更短、更快:
numba:
precomp: 132.957 ms
main 238.359 ms
flat indexing:
precomp: 76.223 ms
main: 219.910 ms
Run Code Online (Sandbox Code Playgroud)
代码:
import numpy as np
from numba import jit
@jit
def fast(A, B, mapping):
N, M = B.shape
for i in range(N):
for j in range(M):
B[i, j] = A[mapping[i, j, 0], mapping[i, j, 1]]
return B
from timeit import timeit
A = np.random.random((5000, 3000))
mapping = np.random.randint(0, 15000, (5000, 3000, 2)) % [5000, 3000]
a = np.random.random((5, 3))
m = np.random.randint(0, 15, (5, 3, 2)) % [5, 3]
print('numba:')
print(f"precomp: {timeit('b = fast(a, np.empty_like(a), m)', globals=globals(), number=1)*1000:10.3f} ms")
print(f"main {timeit('B = fast(A, np.empty_like(A), mapping)', globals=globals(), number=10)*100:10.3f} ms")
print('\nflat indexing:')
print(f"precomp: {timeit('map_f = np.ravel_multi_index((*np.moveaxis(mapping, 2, 0),), A.shape)', globals=globals(), number=10)*100:10.3f} ms")
map_f = np.ravel_multi_index((*np.moveaxis(mapping, 2, 0),), A.shape)
print(f"main: {timeit('B = A.ravel()[map_f]', globals=globals(), number=10)*100:10.3f} ms")
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
192 次 |
| 最近记录: |