の 3 つの配列から始めましょうdtype=np.double
。icc
タイミングは、Intelの でコンパイルおよびリンクされた numpy 1.7.1 を使用して Intel CPU で実行されmkl
ます。gcc
コンパイルなしでコンパイルされた numpy 1.6.1 を搭載した AMD CPUmkl
も、タイミングの検証に使用されました。タイミングはシステム サイズにほぼ比例して変化することに注意してください。これは、numpy 関数if
ステートメントで発生する小さなオーバーヘッドが原因ではないことに注意してください。これらの違いは、ミリ秒ではなくマイクロ秒で現れます。
arr_1D=np.arange(500,dtype=np.double)
large_arr_1D=np.arange(100000,dtype=np.double)
arr_2D=np.arange(500**2,dtype=np.double).reshape(500,500)
arr_3D=np.arange(500**3,dtype=np.double).reshape(500,500,500)
まず、np.sum
関数を見てみましょう:
np.all(np.sum(arr_3D)==np.einsum('ijk->',arr_3D))
True
%timeit np.sum(arr_3D)
10 loops, best of 3: 142 ms per loop
%timeit np.einsum('ijk->', arr_3D)
10 loops, best of 3: 70.2 ms per loop
権限:
np.allclose(arr_3D*arr_3D*arr_3D,np.einsum('ijk,ijk,ijk->ijk',arr_3D,arr_3D,arr_3D))
True
%timeit arr_3D*arr_3D*arr_3D
1 loops, best of 3: 1.32 s per loop
%timeit np.einsum('ijk,ijk,ijk->ijk', arr_3D, arr_3D, arr_3D)
1 loops, best of 3: 694 ms per loop
外装品:
np.all(np.outer(arr_1D,arr_1D)==np.einsum('i,k->ik',arr_1D,arr_1D))
True
%timeit np.outer(arr_1D, arr_1D)
1000 loops, best of 3: 411 us per loop
%timeit np.einsum('i,k->ik', arr_1D, arr_1D)
1000 loops, best of 3: 245 us per loop
上記のすべては、 を使用すると 2 倍高速になりnp.einsum
ます。すべてが具体的にdtype=np.double
. 次のような操作でスピードアップが期待できます。
np.allclose(np.sum(arr_2D*arr_3D),np.einsum('ij,oij->',arr_2D,arr_3D))
True
%timeit np.sum(arr_2D*arr_3D)
1 loops, best of 3: 813 ms per loop
%timeit np.einsum('ij,oij->', arr_2D, arr_3D)
10 loops, best of 3: 85.1 ms per loop
np.inner
Einsum は、np.outer
、 、np.kron
、および選択にnp.sum
関係なく、少なくとも 2 倍高速であるようaxes
です。主な例外はnp.dot
、BLAS ライブラリから DGEMM を呼び出す場合です。np.einsum
では、同等の他のnumpy関数よりも速いのはなぜですか?
完全を期すための DGEMM ケース:
np.allclose(np.dot(arr_2D,arr_2D),np.einsum('ij,jk',arr_2D,arr_2D))
True
%timeit np.einsum('ij,jk',arr_2D,arr_2D)
10 loops, best of 3: 56.1 ms per loop
%timeit np.dot(arr_2D,arr_2D)
100 loops, best of 3: 5.17 ms per loop
主な理論は、 SSE2np.einsum
を利用できる@sebergs コメントからのものですが、numpy の ufuncs は numpy 1.8 まで利用できません (変更ログを参照)。私はこれが正しい答えだと信じていますが、それを確認することはできませんでした. 入力配列の dtype を変更し、速度の違いと、すべての人がタイミングの同じ傾向を観察しているわけではないという事実を観察することによって、いくつかの限定的な証拠を見つけることができます。