カスタムufuncを書く必要なく、メモリ内の各要素に1回アクセスする(時間効率が良い)方法はありますか?
はい、これはまさにnumexpr
のためのものです。
import numpy as np
import numexpr as ne
def func1(A, B):
A = A ** 3
A = np.maximum(A, 0.001)
return np.divide(B, A)
def func2(A, B):
return ne.evaluate("B/where(A**3 > 0.001, A**3, 0.001)",
local_dict={'A':A,'B':B})
A, B = np.random.randn(2, 1000, 1000, 3)
print(np.allclose(func1(A, B), func2(A, B)))
# True
numexpr
あなたの元のコードの上に70倍の改善について示します:
In [1]: %%timeit A, B = np.random.randn(2, 1000, 1000, 3)
func1(A, B)
....:
1 loop, best of 3: 837 ms per loop
In [2]: %%timeit A, B = np.random.randn(2, 1000, 1000, 3)
func2(A, B)
....:
The slowest run took 8.87 times longer than the fastest. This could mean that an
intermediate result is being cached.
100 loops, best of 3: 11.5 ms per loop
一部でnumexpr
が、それはそれでも、単一のスレッドで、デフォルトでは計算のために複数のスレッドを使用するためでありますまだ素朴なベクトル化を押しつぶす:
In [3]: ne.set_num_threads(1)
Out[3]: 8
In [4]: %%timeit A, B = np.random.randn(2, 1000, 1000, 3)
func2(A, B)
....:
10 loops, best of 3: 47.3 ms per loop
3番目のリンクを使用するデータ型では、 'A *** 3'をシミュレートするために' np.einsum( 'ijk、ijk、ijk-> ijk'、A、A、A)を実行できますか?それは本当に効率的なはずです。 – Divakar