NumPy广播如何实现更快速的计算?

7
在下面的问题中, https://dev59.com/51kS5IYBdhLWcg3wUFB0#40056135 Numpy的广播提供了一个解决方案,比使用np.setdiff1d()和np.view()组合使用快了近6倍。它是如何做到的?
而使用A[~((A[:,None,:] == B).all(-1)).any(1)]可以进一步加速。有趣的是,这是如何实现更好的性能的?

相对于什么而言更快? - Bakuriu
我的错。与使用np.setdiff1d配对的np.view相比更快。 - R. S. Nikhil Krishna
1
这并不是一个全面的答案,但是 setdiff1d 在幕后需要进行大量的完整排序操作,而上面的代码行只是分配了一个内存块,填充它,然后将其缩减为一个一维数组以索引 A。然而,当 AB 变得更大时(可能需要分配和填充大量的内存块),使用诸如 (A[:,None,:] == B) 的代码会变得非常低效,因此它实际上可能会变成更慢的选项。 - Alex Riley
1个回答

5

我会尝试回答问题的第二部分。

所以,我们正在比较:

A[np.all(np.any((A-B[:, None]), axis=2), axis=0)]  (I)

而且。
A[~((A[:,None,:] == B).all(-1)).any(1)]

与第一种方法进行匹配对比,我们可以将第二种方法写成这样 -
A[(((~(A[:,None,:] == B)).any(2))).all(1)]         (II)

主要区别在于性能方面,第一种方法使用减法获取非匹配值,并检查.any()中的非零值。因此,any()被设计用于处理非布尔类型数组。而在第二种方法中,我们使用A[:,None,:] == B生成布尔数组并将其传递给any()
让我们进行一个小型的运行时测试以查看.any()int dtype和boolean array上的表现 -
In [141]: A = np.random.randint(0,9,(1000,1000)) # An int array

In [142]: %timeit A.any(0)
1000 loops, best of 3: 1.43 ms per loop

In [143]: A = np.random.randint(0,9,(1000,1000))>5 # A boolean array

In [144]: %timeit A.any(0)
10000 loops, best of 3: 164 µs per loop

所以,通过在这部分上近乎9倍的加速,我们看到使用布尔数组的any()方法有巨大优势。我认为这是使第二种方法更快的最大原因。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接