numpy.searchsorted的性能在结构化数组上很差

Lev*_*sky 15 python arrays numpy binary-search

提前抱歉,如果我误用了任何条款,请随时纠正.

我有一个排序数组dtype '<f16, |S30'.当我searchsorted在它的第一个字段上使用时,它的工作速度非常慢(对于300万个项目,大约需要0.4秒).这比bisect在元组的普通Python列表上做同样的事情要长得多.

%timeit a['f0'].searchsorted(400.)
1 loops, best of 3: 398 ms per loop
Run Code Online (Sandbox Code Playgroud)

但是,如果我将float部分复制到另一个单独的数组,则搜索速度快于bisect:

b = a['f0'].copy()

%timeit b.searchsorted(400.)
1000000 loops, best of 3: 945 ns per loop
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  1. 我做错了什么还是在NumPy中回归?
  2. 有没有办法绕过这个而不重复数据?

Bi *_*ico 13

我记得很久以前见过这个.如果我没记错的话,我认为当数据不连续时,searchsorted会生成数据的临时副本.如果我以后有时间,我会查看代码以确认发生了什么(或者可能更熟悉代码的人可以确认这一点).

同时,如果您不想重构代码以避免使用结构化数组,那么您最好的选择就是使用bisect_left(a['f0'], 400.).在我的机器上,它比连续阵列上的searchsorted慢8倍,但比非连续阵列上的searchsorted快1000倍.

In [5]: a = np.arange((6e6)).view([('f0', float), ('f1', float)])

In [6]: timeit a['f0'].searchsorted(400.)
10 loops, best of 3: 51.1 ms per loop

In [7]: timeit a['f0'].copy()
10 loops, best of 3: 51 ms per loop

In [8]: timeit bisect_left(a['f0'], 400.)
10000 loops, best of 3: 52.8 us per loop

In [9]: f0 = a['f0'].copy()

In [10]: timeit f0.searchsorted(400.)
100000 loops, best of 3: 7.85 us per loop
Run Code Online (Sandbox Code Playgroud)