numpy中的提取比花式索引慢?

时间:2014-02-17 16:38:17

标签: python numpy

Ndarray有一个成员函数extract来提取满足某些条件的数组元素。但是,此功能比花式索引慢。我们为什么要使用这个功能?

from numpy import *
a=random.random((1000,2000))
b=a>0.2
%timeit extract(b,a)
%timeit a[b]
%timeit extract(a>0.2,a)
%timeit a[a>0.2]

这是我的输出:

In [138]: %timeit extract(b,a)
10 loops, best of 3: 29.6 ms per loop

In [139]: %timeit a[b]
100 loops, best of 3: 18.5 ms per loop

In [140]: %timeit extract(a>0.2,a)
10 loops, best of 3: 31.4 ms per loop

In [141]: %timeit a[a>0.2]
10 loops, best of 3: 19.7 ms per loop

1 个答案:

答案 0 :(得分:1)

如果我们检查np.extract,我们会发现以下内容:

take(a.ravel(), nonzero(ravel(b))[0])

这里有趣的是我们取b这是一个布尔数组并将其转换为索引,以便正常的np.take操作可以像宣传的那样工作。如果我们检查这需要多长时间,我们会发现nonzero占总时间的大部分时间,并且花哨索引所需的时间少于nonzero

%timeit nonzero(ravel(b))[0]
100 loops, best of 3: 13.1 ms per loop

%timeit take(a.ravel(), nonzero(ravel(b))[0])
100 loops, best of 3: 18.7 ms per loop

%timeit a[b]
100 loops, best of 3: 12.9 ms per loop

docs解释说即使是花哨的索引也会使用某种类似nonzero的操作来创建索引数组;但是,花哨的索引不涉及python抽象层。我相信python抽象层是这里的关键。到底究竟是什么,我不打算推​​测,但我希望当函数纯粹在C方面时会发生很多优化(就像所有花哨的索引一样)。