2017-03-11 6 views
0

私は、numpy.takeが空想的なインデックス付けのはるかに速い代替手段であることを多くの異なる場所で読んでいます。例えば、herehereです。numpy.takeよりもはるかに高速なインデックス作成ですか?

しかし、私はこれが事実であるとは思っていません...まったくありません。ここで私はいくつかのデバッグ中に私のコードの周り突っついたときからの例です:

ファンシーインデックスははるかに高速であることを示している
knn_idx 
Out[2]: 
array([ 3290, 5847, 7682, 6957, 22660, 5482, 22661, 10965,  7, 
     1477, 7681,  3, 17541, 15717, 9139, 1475, 14251, 4400, 
     7680, 9140, 4758, 22289, 7679, 8407, 20101, 15718, 15716, 
     8405, 15710, 20829, 22662], dtype=uint32) 
%timeit X.take(knn_idx, axis=0) 
100 loops, best of 3: 3.14 ms per loop 
%timeit X[knn_idx] 
The slowest run took 60.61 times longer than the fastest. This could mean that an intermediate result is being cached. 
100000 loops, best of 3: 5.48 µs per loop 
X.shape 
Out[5]: 
(23011, 30) 
X.dtype 
Out[6]: 
dtype('float64') 

!私は同様の結果を得るためのインデックスを生成するnumpy.arangeを使用した:

idx = np.arange(0, len(X), 100) 
%timeit X.take(idx, axis=0) 
100 loops, best of 3: 3.04 ms per loop 
%timeit X[idx] 
The slowest run took 9.41 times longer than the fastest. This could mean that an intermediate result is being cached. 
10000 loops, best of 3: 20.7 µs per loop 

なぜファンシーインデックスは今numpy.takeを使用するよりもそんなに速いのですか?私は何らかの縁起を打つのだろうか?

私はアナコンダ経由のPython 3.6を使用して、ここで、関連するならば、私のnumpyの情報ですよ。私のテストでは

np.__version__ 
Out[11]: 
'1.11.3' 
np.__config__.show() 
blas_mkl_info: 
    libraries = ['mkl_core_dll', 'mkl_intel_lp64_dll', 'mkl_intel_thread_dll'] 
    library_dirs = ['C:/Users/pbreach/Continuum/Anaconda3\\Library\\lib'] 
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)] 
    include_dirs = ['C:/Users/pbreach/Continuum/Anaconda3\\Library\\include'] 
blas_opt_info: 
    libraries = ['mkl_core_dll', 'mkl_intel_lp64_dll', 'mkl_intel_thread_dll'] 
    library_dirs = ['C:/Users/pbreach/Continuum/Anaconda3\\Library\\lib'] 
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)] 
    include_dirs = ['C:/Users/pbreach/Continuum/Anaconda3\\Library\\include'] 
openblas_lapack_info: 
    NOT AVAILABLE 
lapack_mkl_info: 
    libraries = ['mkl_core_dll', 'mkl_intel_lp64_dll', 'mkl_intel_thread_dll'] 
    library_dirs = ['C:/Users/pbreach/Continuum/Anaconda3\\Library\\lib'] 
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)] 
    include_dirs = ['C:/Users/pbreach/Continuum/Anaconda3\\Library\\include'] 
lapack_opt_info: 
    libraries = ['mkl_core_dll', 'mkl_intel_lp64_dll', 'mkl_intel_thread_dll'] 
    library_dirs = ['C:/Users/pbreach/Continuum/Anaconda3\\Library\\lib'] 
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)] 
    include_dirs = ['C:/Users/pbreach/Continuum/Anaconda3\\Library\\include'] 

答えて

1

takeは控えめに高速です。しかし、わずかな時間と私は違いの株式の多くを入れていない「キャッシュされた」警告:

In [192]: timeit X.take(idx2, axis=0).shape 
The slowest run took 23.29 times longer than the fastest. This could mean that an intermediate result is being cached. 
100000 loops, best of 3: 3.66 µs per loop 
In [193]: timeit X[idx2,:].shape 
The slowest run took 16.75 times longer than the fastest. This could mean that an intermediate result is being cached. 
100000 loops, best of 3: 5.58 µs per loop 

しかし、あなたのインデックス配列はuint32です。それはインデックス付けでうまくいったが、takeは私に鋳込みエラーを与えた。だから私のidx2astype(int)です。

そしてアレンジidxでは、時間は11.5μs、16μsです。

通知タイミングは.shapeです。違いがあるかどうかは完全にはわかりません。

私はあなたがなぜあなたのためにms時間を得ているのかわかりません。それはtakeの実際の違いよりもタイミングの問題の方が多いように感じます。

私は図書館ではありませんが、BLASなどが違います。基礎となるタスクは基本的に同じです。データバッファをステップ実行し、選択したバイトをコピーします。育つ複雑な計算はありません。しかし、私はtakeのCコードを研究していません。

Numpyバージョン '1.12.0'、Linux、4GB改装デスクトップ。

+0

奇妙なことに、私の2番目のテストでは、 'int32'のインデックス配列を使っていて、最初のものと似たタイミングを得ました。 – pbreach

+0

最も遅い実行でさえ、 'int32'インデックスではまだ約15倍高速でした。 – pbreach

+0

良い点今私は、一般的ではなく特定のケースで「take」が間違っているのではないかと思っています。私はまた、タイミングの中に 'シェイプ 'を含めるようにも試みます。 – pbreach

関連する問題