我有以下问题,我目前使用的解决方案太慢了。
**示例:**形状为(B,2)
的numpy数组b
,形状为(X)
的排序numpy数组x
,形状为(Y)
的排序numpy数组y
。
注意x = np.unique(b[:,0])
和y = np.unique(b[:,1])
,如果这对问题有区别的话。
**任务:**构建(X,Y)
-array H
,使得H[i,j]
是b
中第一个条目小于x[i]
且第二个条目小于y[j]
的行数。
下面的示例代码解决了这个问题:
import numpy as np
b = np.random.random((2000,2))
x = np.unique(b[:,0])
y = np.unique(b[:,1])
H = np.count_nonzero(
np.logical_and(
b[:,0,None,None] <= x[None,:,None],
b[:,1,None,None] <= y[None,None,:]
),
axis=0
)
但是如果b
以及因此x
和y
具有几千个条目,则这变得相当慢。
我如何才能更有效地做到这一点?
1条答案
按热度按时间wgeznvg71#
算法
您当前的实现很好地进行了向量化,但与可以完成的工作相比,它计算的工作量太大了。主要的问题是这个实现的算法复杂度是**
O(n**3)
。这个问题可以用
O(n**2)
算法解决。这是最佳复杂度**,因为H
至少需要填充。关键是对b
按y
进行排序,以便在计算H
行时有效地计算条目的数量。排序后的数组需要通过x
进行过滤,这样就不用关心热循环中的x
值。注意,这种方法假设x
和y
是排序的,因为np.unique
对值进行排序。实现
为了提高实现的性能,可以使用Numba和多线程。注意内存布局对算法缓存友好也很重要。
下面是最终的实现:
性能结果
以下是在我的i5- 9600 KF机器上使用所提供的输入的性能结果:
因此,这种实现方式的速度是2565倍!