2016-05-18 23 views
1

int8のベクトルで最も頻度の高い数値を計算しています。numbaのint配列

TypingError: Invalid usage of Function(<built-in function zeros>) with parameters (int64, Function(<class 'int'>)) 

私はdtype=intを削除した場合、それが動作し、私はまともなスピードアップを得る:

@jit(nopython=True) 
def freq_int8(y): 
    """Find most frequent number in array""" 
    count = np.zeros(256, dtype=int) 
    for val in y: 
     count[val] += 1 
    return ((np.argmax(count)+128) % 256) - 128 

は、私は次のエラーを取得することを呼び出す:私はint秒のカウンタ配列を設定するときNumbaは文句を言います。私はなぜintの配列を宣言するのがうまくいかないのかと困惑しています。既知の回避策がありますか?ここにある価値のある効率向上がありますか?

背景:私はいくつかのコードが重いコードから数マイクロ秒を節約しようとしています。私は特にnumpy.medianで傷ついていて、Numbaを探していましたが、改善するのに苦労していますmedian。最も頻繁な番号を見つけることはmedianの代わりに受け入れられるものであり、ここではいくつかのパフォーマンスを得ることができました。上記のnumbaコードもnumpy.bincountより高速です。

更新:受け入れられた回答の入力後、int8ベクターの場合はmedianの実装があります。

@jit(nopython=True) 
def median_int8(y): 
    N2 = len(y)//2 
    count = np.zeros(256, dtype=np.int32) 
    for val in y: 
     count[val] += 1 
    cs = 0 
    for i in range(-128, 128): 
     cs += count[i] 
     if cs > N2: 
      return float(i) 
     elif cs == N2: 
      j = i+1 
      while count[j] == 0: 
       j += 1 
      return (i + j)/2 

驚くべきことに、パフォーマンスの差はnumpyベクトルで明らかに伴うオーバーヘッドに、短いベクトルについても、大きい:

>>> a = np.random.randint(-128, 128, 10) 

>>> %timeit np.median(a) 
    The slowest run took 7.03 times longer than the fastest. This could mean that an intermediate result is being cached. 
    10000 loops, best of 3: 20.8 µs per loop 

>>> %timeit median_int8(a) 
    The slowest run took 11.67 times longer than the fastest. This could mean that an intermediate result is being cached. 
    1000000 loops, best of 3: 593 ns per loop 

は、このオーバーヘッドが非常に大きいことは、より高速な大きさの順numpy.medianよりおおよそです私は何かが間違っているのだろうかと思っています。最も頻繁番号を見つけるだけで簡単なメモ

答えて

4

は、通常modeと呼ばれ、それはかなり速くなります。その場合np.mean平均 ...であるとして、それは中央値と同様です。あなたのデータに制約や特殊性がない限り、there is no guarantee that the mode approximates the median

あなたはまだあなたが言及として、(numbaが速い場合、それはあまりであってはならない)十分なはずです、整数のリスト、np.bincountモードを計算したい場合:

count = np.bincount(y, minlength=256) 
result = ((np.argmax(count)+128) % 256) - 128 

注意minlengthパラメータをnp.bincountに追加したので、コードにある同じ長さのリストが返されます。しかし、実際には完全に不要です。argmax、(minlengthなし)は、yの最大数のリストを返します。

numbaエラーについては、dtype=intdtype=np.int32に置き換えて問題を解決する必要があります。 intはPython関数で、numbaヘッダーにnopythonを指定しています。 nopythonを削除すると、dtype=intまたはdtype='i'のいずれかが機能します(同じ効果があります)。

+0

これは、_mode_が意味するものです。はい、私は中央値との違いを理解していますが、私の特定のユースケースでは、おそらく中央値よりモードが適切です。 dtype = np.int32を使用することをお勧めします。実際に動作し、さらに30%のスピードアップを提供します。 'bincount'については、それも望み通りに動作しますが、numbaバージョンの約半分です。 – DNF

+1

@DNF numbaは実際にはbincountより高速ですが、numbaの最初の呼び出しは、(非常に大きな配列で呼び出すのでない限り)常に遅いことに注意してください。関数を1回だけ(小さな配列で)呼び出すように定義している場合、速度は 'np.bincount'よりもかなり悪くなります。一方、関数を複数回呼び出す場合や、numbaが最適化できるように配列を大量に配列している場合は、numbaはうまく動作するはずです。 –

+0

セッションあたり数百万、数十または数百万回実行され、複数のプロセッサで実行されます。しかし、新しいプロセスを開始すると新しいコンパイルがトリガーされるかどうかはわかりますか? – DNF