2013-09-04 42 views
6

スクリプトを書いているうちにnumpy.random.choice関数が見つかりました。同等のif文よりもはるかにきれいだったので実装しました。しかし、スクリプトを実行した後、私はそれがであることに気づいた。はif文よりも遅い。random.choiceが遅いのはなぜですか?

以下はMWEです。最初のメソッドは0.0秒かかりますが、2番目のメソッドは7.2秒かかります。 iループをスケールアップすると、random.choiceの速度が遅くなるのがわかります。

誰かがrandom.choiceが非常に遅いのはなぜですか?

import numpy as np 
import numpy.random as rand 
import time as tm 

#------------------------------------------------------------------------------- 

tStart = tm.time() 
for i in xrange(100): 
    for j in xrange(1000): 
     tmp = rand.rand() 
     if tmp < 0.25: 
      var = 1 
     elif tmp < 0.5: 
      var = -1 
print('Time: %.1f s' %(tm.time() - tStart)) 

#------------------------------------------------------------------------------- 

tStart = tm.time() 
for i in xrange(100): 
    for j in xrange(1000): 
     var = rand.choice([-1, 0, 1], p = [0.25, 0.5, 0.25]) 
print('Time: %.1f s' %(tm.time() - tStart)) 
+3

これは実際に公正な比較ではありません。毎回numpyはpリストの累積合計を新しいベクトルに入れ、それを反復しなければなりません。 3つの変数しかないことを知って事実上前処理をしており、第1と第3の合計は.5です。それを超えると、numpyはベクトル化された演算に最適化されています.1回の簡単な演算を何千回も実行するのではなく、 –

+1

また、 'time'ではなく、' timeit'を単独で使用してください。 – Marcin

答えて

12

これは間違っています。操作をベクトル化、またはnumpyのは、何の利点を提供しません:

var = numpy.random.choice([-1, 0, 1], size=1000, p=[0.25, 0.5, 0.25]) 

タイミングデータ:

>>> timeit.timeit('''numpy.random.choice([-1, 0, 1], 
...          size=1000, 
...          p=[0.25, 0.5, 0.25])''', 
...    'import numpy', number=10000) 
2.380380242513752 

>>> timeit.timeit(''' 
... var = [] 
... for i in xrange(1000): 
...  tmp = rand.rand() 
...  if tmp < 0.25: 
...   var.append(1) 
...  elif tmp < 0.5: 
...   var.append(-1) 
...  else: 
...   var.append(0)''', 
... setup='import numpy.random as rand', number=10000) 
5.673041396894519 
+2

+1これは最初のループより約7倍高速です。 –

+0

書いてあるとおり、あなたはリンゴをリンゴと比較していますか?最初のものは10^3 * 10^4 = 10^7個の乱数を計算しますが、2番目のものは10^2 * 10^3 * 10^4 = 10^9個の乱数を計算します。 – DSM

+0

@DSM:おっと。間違ったことを時間にコピーした。修理... – user2357112

1

私はnp.random.choiceの一般性が大きなものより小さな試料について、より多くのように、それを減速している疑いがあります。

ifバージョンの粗製のベクトルがある:

ipythonで実行
def foo(n): 
    x = np.random.rand(n) 
    var = np.zeros(n) 
    var[x<.25] = -1 
    var[x>.75] = 1 
    return var 

私が手:

timeit np.random.choice([-1,0,1],size=1000,p=[.25,.5,.25]) 
1000 loops, best of 3: 293 us per loop 

timeit foo(1000) 
10000 loops, best of 3: 83.4 us per loop 

timeit np.random.choice([-1,0,1],size=100000,p=[.25,.5,.25]) 
100 loops, best of 3: 11 ms per loop 

timeit foo(100000) 
100 loops, best of 3: 8.12 ms per loop 

ので1000サイズのため、choiceは3~4倍遅くなりますが、大きなベクターであります、その差は消え始める。