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

时间:2018-11-22 04:31:29

标签: python numpy

我正在使用numpy实现某种搜索算法,其中一步是检查天气,矢量在矩阵中(作为行)。我以前曾经使用过np.isin,但是突然间我就好奇python关键字in是否可以工作。因此,我对其进行了测试,发现它可以正常工作。

由于我没有找到in的任何python接口(例如__add__的{​​{1}}或+的{​​{1}}),我相信{{1 }}使用标准的迭代器逻辑在python中进行了硬连线,因此,与__abs__提供的abs相比,它应该更慢。但是令人难以置信的是,在我进行了一些测试之后:

in

对于小数据类型,这表示numpy比python np.isin慢10倍以上。我还对大数据类型进行了测试

>>> a = np.int8(1)
>>> A = np.zeros(2**24, 'b')
>>> %timeit a in A
>>> %timeit np.isin(a, A)
21.7 ms ± 1.58 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
310 ms ± 20.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

这表示np.isin慢100倍。

我想知道这可能是什么原因。请注意,自in>>> a = np.ones(1, 'V256') >>> A = np.zeros(2**22, 'V256') >>> %timeit a in A >>> %timeit np.isin(a, A) 129 ms ± 12.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 10.5 s ± 184 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 以来,必须在整个数组上进行匹配。在python端没有“早退”之类的东西。

编辑哦,实际上np.isin有一个名为a=1的python接口。但是为什么A=[0,0,...]会比in慢呢?

2 个答案:

答案 0 :(得分:2)

numpy.ndarray.__contains__基本上只是(elem == arr).any()(即使那没有意义)。您可以看看source,它对于NumPy C例程而言非常简短。

numpy.isin在其左操作数上进行广播,并且针对广播情况下的效率进行了优化。对于较小的左操作数,它将使用an approach based on sorting,对于标量而言这是过大的。当前,对于左操作数为标量,或者对于左手为足够小的数组,以至于排序比单纯的方法要昂贵的多,目前尚无捷径。

答案 1 :(得分:-1)

我的答案与要求不符。可能会给你一些想法。通常,从numpy获得良好性能的主要想法是一次分摊许多元素上的解释器成本。换句话说,将循环从python代码(慢)移到numpy / BLAS / LAPACK / etc中的C / Fortran循环。内部(快速)。如果您成功执行了该操作(称为矢量化),则性能通常会很好。

当然,通过转储python解释器并改为使用C ++,显然可以提高性能。这种方法是否真正成功取决于您对C ++和numpy的高性能编程的熟练程度,以及您要尝试执行的操作。