我正在使用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
慢呢?
答案 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的高性能编程的熟练程度,以及您要尝试执行的操作。