3

次のテンソル実行があります。

np.einsum('k,pjqk,yzjqk,yzk,ipqt->it', A, B, C, D, E)

そして、'z' または 'q' の次元が拡張されると、実行時間が非常に長くなることに気付きました。私の直感では、おそらくそれほど悪くはないはずでした。手動のテンソル収縮によって最適化できたのは私の入力フォームだったのかもしれません。

少し掘り下げた後、最適化には「最適」と「貪欲」の2つのモードがあることがわかりました。両方のモードに対してパスを評価した場合、それぞれ次のようになります。

(['einsum_path', (0, 3), (1, 3), (0, 2), (0, 1)],
'  Complete contraction:  k,pjqk,yzjqk,yzk,ipqt->it\n'
'         Naive scaling:  8\n'
'     Optimized scaling:  5\n'
'      Naive FLOP count:  5.530e+04\n'
'  Optimized FLOP count:  7.930e+02\n'
'   Theoretical speedup:  69.730\n'
'  Largest intermediate:  2.400e+01 elements\n'
'--------------------------------------------------------------------------\n'
'scaling                  current                                remaining\n'
'--------------------------------------------------------------------------\n'
'   3                  yzk,k->yzk                  pjqk,yzjqk,ipqt,yzk->it\n'
'   5              yzk,yzjqk->jqk                        pjqk,ipqt,jqk->it\n'
'   4                jqk,pjqk->qp                              ipqt,qp->it\n'
'   4                 qp,ipqt->it                                   it->it')

(['einsum_path', (2, 3), (1, 3), (1, 2), (0, 1)],
'  Complete contraction:  k,pjqk,yzjqk,yzk,ipqt->it\n'
'         Naive scaling:  8\n'
'     Optimized scaling:  5\n'
'      Naive FLOP count:  5.530e+04\n'
'  Optimized FLOP count:  1.729e+03\n'
'   Theoretical speedup:  31.981\n'
'  Largest intermediate:  4.800e+01 elements\n'
'--------------------------------------------------------------------------\n'
'scaling                  current                                remaining\n'
'--------------------------------------------------------------------------\n'
'   5              yzk,yzjqk->jqk                      k,pjqk,ipqt,jqk->it\n'
'   4               jqk,pjqk->qkp                           k,ipqt,qkp->it\n'
'   5               qkp,ipqt->tik                                k,tik->it\n'
'   3                   tik,k->it                                   it->it')

テストした結果は、示されているように、「最適」の方がはるかに高速であるということです。

質問

違いが何であり、「貪欲」がデフォルトに設定されている理由を簡単に説明できる人はいますか?

常に「最適」を使用することの欠点は何ですか?

私の einsum 計算が何千回も実行される場合 (これは最適化の反復の一部として実行されます)、実行を再構築して、再計算する必要なく (または「貪欲な」パス)毎回?

4

1 に答える 1

2

もう少し読むと、これを見つけた人のために次のことが明らかになりました。

「貪欲」は一般に、ほとんどの使用ケースで「最適な」ソリューションを生成する非常にパフォーマンスが高く、実行が高速です。反復ループで不注意に einsum を使用する可能性がある一般ユーザーの場合、おそらくデフォルトのままで十分でしょう。

それ以外の場合、1回限りの計算では、「最適」の最小の追加オーバーヘッドは、おそらく多数のインデックスを除いて効果的に使用できることを意味し、大きなブーストを提供する可能性があるようです(私の場合のように)。

ループ内で行う最善の方法は、それを事前に計算し (または最初の反復で計算して非ローカル変数を更新し)、それを引数として提供することです。

path, display = np.einsum_path('k,pjqk,yzjqk,yzk,ipqt->it', A, B, C, D, E, optimize='optimal')
for i in range(BIG_INT):
    # other things
    calculation = np.einsum_path('k,pjqk,yzjqk,yzk,ipqt->it', A, B, C, D, E, optimize=path)
    # more things
于 2018-03-14T15:14:26.410 に答える