2017-11-13 5 views
4

numbaのjitコンパイラで条件の配列を含む関数をコンパイルしようとすると、非常に時間がかかります。プログラムは基本的にはnumba.jitによる条件配列のコンパイルに長時間かかる

from numba import jit 
import numpy as np 

@jit(nopython=True) 
def foo(a, b): 
    valid = [ 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0), 
     (a - 1 >= 0) and (b - 1 >= 0) 
    ] 

foo(1, 1) 

のように見えますが、ここではコンパイル時間を大幅に変更しないものはすべて除外しています。私は20以上の要素を使用すると問題が発生します。

| elements | time | 
------------------- 
| 21 | 2.7s | 
| 22 | 5.1s | 
| 23 | 10s | 
| ... | ... | 
------------------- 

でも、この機能はうまく機能します。 numbaでそのような関数をコンパイルするのは誰にも分かりません。整数や浮動小数点数の組み合わせで同様の方法で配列を作成することは問題ありません。それはそう悪いスケールするために何かがコンパイラにゆがんで起こっているようにあなたがnumba issue trackerにこれを報告したいことがあり

+0

あなたが実行可能である完全な例を提供することはできますか? – JoshAdel

+0

@JoshAdel私はこの例を変更しました。これは現在実行可能で簡単です。 – TheIdealis

答えて

2
  1. は、感じています。

  2. また、このような数多くの配列ステートメントが本当に必要かどうか、問題がより明確にリファクタリングできるかどうかを検討することもできます。例えば。ブール値の配列ではなく、validという関数を必要に応じて呼び出すことができますか?

  3. つまり、現在のバージョンのnumbaの回避策は、条件を展開することです。ご例えば

# "codegen" 
for i in range(23): 
    print(f' valid[{i}] = (a - 1 >= 0) and (b - 1 >= 0)') 

@jit(nopython=True) 
def foo(a, b): 
    valid = np.empty(23, dtype=np.bool_) 
    valid[0] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[1] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[2] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[3] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[4] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[5] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[6] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[7] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[8] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[9] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[10] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[11] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[12] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[13] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[14] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[15] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[16] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[17] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[18] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[19] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[20] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[21] = (a - 1 >= 0) and (b - 1 >= 0) 
    valid[22] = (a - 1 >= 0) and (b - 1 >= 0) 

%time foo(1,1) 
Wall time: 274 ms 
+0

私の元の関数では、すべての条件が異なっていて、 'valid'で複数の他の配列をインデックスしなければなりませんでした。 if文の代わりに配列を使う方が、より高速で読みやすいオプションのように思えました。私は[ここ](https://github.com/numba/numba/issues/2611)の問題を提起し、何かが変わると私の質問を更新します。 – TheIdealis

関連する問題