为什么 python `in` 比 `np.isin` 快得多

Zis*_*Zis 2 python numpy

我正在实现一些搜索算法,numpy其中一个步骤是检查向量是否在矩阵中(作为行)。我以前用过np.isin,但我突然很好奇 python 关键字是否in有效。因此我对其进行了测试,发现它确实有效。

\n\n

由于我没有找到任何 python 接口in(例如__add__for+__abs__for abs),我相信in通过使用标准迭代器逻辑在 python 中进行硬连接,因此它应该比 -providednumpynp.isin。但在我做了一些测试之后,令人难以置信的是:

\n\n
>>> a = np.int8(1)\n>>> A = np.zeros(2**24, \'b\')\n>>> %timeit a in A\n>>> %timeit np.isin(a, A)\n21.7 ms \xc2\xb1 1.58 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 10 loops each)\n310 ms \xc2\xb1 20.4 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 1 loop each)\n
Run Code Online (Sandbox Code Playgroud)\n\n

对于小数据类型,这np.isin比 python 慢 10 倍以上in。我还做了一个大数据类型的测试

\n\n
>>> a = np.ones(1, \'V256\')\n>>> A = np.zeros(2**22, \'V256\')\n>>> %timeit a in A\n>>> %timeit np.isin(a, A)\n129 ms \xc2\xb1 12.2 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 1 loop each)\n10.5 s \xc2\xb1 184 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 1 loop each)\n
Run Code Online (Sandbox Code Playgroud)\n\n

也就是说np.isin慢了大约 100 倍。

\n\n

我想知道这可能是什么原因。请注意,从a=1while 开始A=[0,0,...],匹配必须在整个数组上完成。python 方面不存在“提前退出”这样的事情。

\n\n

编辑哦,实际上有一个用于in调用的python 接口__contains__。但为什么会np.isin比 慢得多np.ndarray.__contains__

\n

use*_*ica 6

numpy.ndarray.__contains__基本上是公正的(elem == arr).any()(即使这没有意义)。您可以查看源代码,它对于 NumPy C 例程来说非常简短。

numpy.isin通过其左操作数进行广播,并且针对广播情况下的效率进行了优化。对于较小的左操作数,它将使用基于排序的方法,这对于标量来说是过度的。目前,对于左操作数是标量,或者左操作数是足够小的数组,排序比简单的方法更昂贵,目前没有快速路径。