numbaではnumpy.resize
がサポートされていないようです。numbaの関数で動的に配列を配列する
numba.jit
で動的に成長するアレイをnopythonモードで使用する最良の方法は何ですか?
これまでのところ私ができることは、jitted関数の外側で配列を定義してサイズを変更することでしたが、より良い(そしてより良い)オプションがありますか?
numbaではnumpy.resize
がサポートされていないようです。numbaの関数で動的に配列を配列する
numba.jit
で動的に成長するアレイをnopythonモードで使用する最良の方法は何ですか?
これまでのところ私ができることは、jitted関数の外側で配列を定義してサイズを変更することでしたが、より良い(そしてより良い)オプションがありますか?
numpy.resize
はpure python functionです:
import numpy as np
def resize(a, new_shape):
"""I did some minor changes so it all works with just `import numpy as np`."""
if isinstance(new_shape, (int, np.core.numerictypes.integer)):
new_shape = (new_shape,)
a = np.ravel(a)
Na = len(a)
if not Na:
return np.zeros(new_shape, a.dtype)
total_size = np.multiply.reduce(new_shape)
n_copies = int(total_size/Na)
extra = total_size % Na
if total_size == 0:
return a[:0]
if extra != 0:
n_copies = n_copies+1
extra = Na-extra
a = np.concatenate((a,)*n_copies)
if extra > 0:
a = a[:-extra]
return np.reshape(a, new_shape)
1Dアレイでは、これは自分で実装する単純明快になります。残念ながら、ND配列の場合、nopythonのnumba関数ではサポートされていない演算がいくつかあるので、これは非常に複雑です。isinstance
,reshape
およびタプル乗算。ここで1Dと同等である:あなたがその「繰り返し入力」行動をしたいだけのためにそれを使用していない
import numpy as np
import numba as nb
@nb.njit
def resize(a, new_size):
new = np.zeros(new_size, a.dtype)
idx = 0
while True:
newidx = idx + a.size
if newidx > new_size:
new[idx:] = a[:new_size-newidx]
break
new[idx:newidx] = a
idx = newidx
return new
はサイズを増やすことがさらに簡単です:
@nb.njit
def resize(a, new_size):
new = np.zeros(new_size, a.dtype)
new[:a.size] = a
return new
これらの機能が飾られていますnumba.njit
であるため、nopythonモードのnumba関数で呼び出すことができます。
しかし注意の単語: - あなたは、あなたがamoritzed O(1)
cost (Wikipedia link)を持ってアプローチを選択するようにしてくださいない場合、または一般的に、あなたは、サイズを変更する必要はありません。最大長を見積もることができれば、正しいサイズの(またはわずかにオーバーレイされた)配列を即座に事前に割り当てるほうがよいでしょう。
通常、私が採用している戦略は、計算に対応するのに十分な数のアレイストレージを割り当ててから、使用される最終インデックス/インデックスを追跡してから、実際のサイズにスライスして戻します。これは、配列を大きくする可能性のある最大サイズを事前に知っていることを前提としています。思ったのは、自分のアプリケーションのほとんどでメモリは安いですが、サイズを変更したり、Pythonとjitted関数を切り替えるのはコストがかかります。
ありがとうございました。私は配列が2の倍数になるようにサイズを変更するので、最終的にはpythonとjitted関数の間でlog(max_size)スイッチを使います。この量の切り替えが実際のボトルネックだと思いますか?実際の問題は、毎回配列をコピーするという1.5倍の要因ですが、私はそれを取り除いて喜んでいますが、それは最大サイズを知らないための価格だと思います(ちょっとばかげた初期サイズでハックを使用するかもしれませんが、 RAMに収まる限り)。 – nivniv
実際にコードをプロファイリングせずにボトルネックになるのは難しいです(cProfileとline_profilerはtimeitのように役に立ちます)。実際には、特定のアプリケーションに依存することになります。 – JoshAdel
ありがとう、それは私が探していたものです。あまりにもND配列のための簡単な解決策はありません。 – nivniv
の代わりに、np.empty(new_size、a.dtype)を使うことができます。 – tal