非常に時間がかかる numpy プログラムを作成しました。プロファイリングを行った後、ほとんどの時間が に費やされていることがわかりましたnumpy.einsum
。
numpy.einsum
numpy は LAPACK または BLAS のラッパーですが、のパフォーマンスが LAPACK または BLAS の対応するものに匹敵するかどうかはわかりません。
では、Fortran や C に切り替えると、パフォーマンスが大幅に向上しますか?
非常に時間がかかる numpy プログラムを作成しました。プロファイリングを行った後、ほとんどの時間が に費やされていることがわかりましたnumpy.einsum
。
numpy.einsum
numpy は LAPACK または BLAS のラッパーですが、のパフォーマンスが LAPACK または BLAS の対応するものに匹敵するかどうかはわかりません。
では、Fortran や C に切り替えると、パフォーマンスが大幅に向上しますか?
BLAS で指定されたプリミティブ操作に対してのみ、BLAS を使用した Numpy ラップ。これには、、、、( dot
1.10の新機能)、およびそれに依存する関数 (など) が含まれます。一方、BLAS にフォールバックできる操作に対してのみ BLAS を呼び出します (Numpy 1.14.0 以降)。innerproduct
vdot
matmul
tensordot
einsum
問題がいくつかの BLAS 操作に分解できる場合は、最初に Numpy 自体でそれを試すことをお勧めします。間にいくつかの一時的な配列が必要になる場合があります (BLAS を使用する C/FORTRAN を作成する場合でも同様です)。out=
関数のパラメーターを使用すると、特定の配列作成オーバーヘッドを排除できます。
しかし、ほとんどの場合einsum
、BLAS では表現できないため、使用しています。簡単な例を見てください:
a = np.arange(60.).reshape(3,4,5)
b = np.arange(24.).reshape(4,3,2)
c = np.einsum('ijk,jil->kl', a, b)
上記をプリミティブ操作で表現するには、最初の 2 つの軸を で交換し、最初のb
2 つの次元に対して要素単位の乗算を行い、次にそれらを合計する必要がk
ありl
ます。
c2 = np.ndarray((5, 2))
b2 = np.swapaxes(b, 0, 1)
def manualeinsum(c2, a, b):
ny, nx = c2.shape
for k in range(ny):
for l in range(nx):
c2[k, l] = np.sum(a[..., k]*b2[...,l])
manualeinsum(c2, a, b2)
それをBLASすることはできません。更新: 上記の問題は、BLAS を使用して高速化できる行列乗算として表すことができます。@ali_m のコメントを参照してください。配列が十分に大きい場合は、BLAS アプローチの方が高速です。
一方、einsum
それ自体は C で書かれており、指定されたインデックスに対して次元固有の反復子を作成し、SSE 用に最適化されていることに注意してください。