2017-10-19 12 views
1

私は可能な限り効率的に実装する必要がある非常に大きな乗算とサム演算を持っています。 Lは、実際には大きくなるだろうということMATLABのbsxfunは最適ですか? Pythonのnumpy.einsum?

L = 10000; 
x = rand(4,1,L+1); 
A_k = rand(4,4,L); 
tic 
for k = 2:L 
    i = 2:k; 
    x(:,1,k+1) = x(:,1,k+1)+sum(sum(bsxfun(@times,A_k(:,:,2:k),x(:,1,k+1-i)),2),3); 
end 
toc 

注:私は今のところ見つけた最善の方法は、私のように問題を定式化MATLABでbsxfunです。より速い方法がありますか?まず、シングルトンディメンションをxに追加してからsumに追加する必要があるのは奇妙ですが、それ以外は機能しません。

私が試した他の方法よりもずっと高速ですが、アプリケーションにとっては十分ではありません。私は、Python関数numpy.einsumが効率的かもしれないという噂を聞いたことがありますが、コードを移植する前に、ここで最初に質問したかったのです。

私はMATLAB R2017bを使用しています。あなたは、MATLABの新しいバージョンを使っているので

+0

多くの場合、forループはbsxfunよりも高速です。しかし、あなたはすでにそれを試しているようだ...? – Adiel

+1

行列の乗算は 'bsxfun'よりも高速ですが、これは簡単にはできません。 –

+0

@LuisMendo問題を疎行列の乗算に変換することを検討しましたが、少し難しいです...もっと早く? – Alex

答えて

5

私はあなたの集計の両方を削除することができますが、私は当面は簡単なものだけを削除しました。ランタイムが〜8秒に〜私のラップトップ上の2.5秒から減少し

B_k = sum(A_k,2); 
for k = 2:L 
    i = 2:k; 
    x(:,1,k+1) = x(:,1,k+1) + sum(bsxfun(@times,B_k(:,1,2:k),x(:,1,k+1-i)),3); 
end 

この単一の変更に伴い:それだけA_k配列に影響を与えますので、二次元以上の合計は、自明です。

times + sumを行列 - ベクトル積に変換することによって、第2の和を取り除くこともできます。次元を正しく取得するには、いくつかのシングルトン手落ちが必要ですが、B_kと2番目の次元を逆にして補助配列を定義する場合は、残りの合計をx*C_kとしてこの補助配列C_kで生成するか、reshape


だからよく見た後、私は私の元の評価が過度に楽観的だったことに気づい:あなたはあなたの残りの期間中に、両方の次元での乗算を持っているので、簡単な行列積ではありません。とにかく、その言葉を行列積の対角に書き換えることができます。 〜これが実行されている

L = 10000; 
x = rand(4,L+1); 
A_k = rand(4,4,L); 
B_k = squeeze(sum(A_k,2)).'; 

tic 
for k = 2:L 
    ii = 1:k-1; 
    x(:,k+1) = x(:,k+1) + diag(x(:,ii)*B_k(k+1-ii,:)); 
end 
toc 

:これは私たちが不要な行列要素の束を計算しているが、これはまだbsxfunアプローチよりも若干速いように思われ、私たちはあまりにもあなたの厄介なシングルトンの次元を取り除くことを意味します私のラップトップでは2.2秒、以前より2.5秒はやや速かった。

+1

うわー!これは私のラップトップでも約4倍高速です。ありがとうございました! – Alex

+1

@Alexは正しいと確信しています。私は大雑把な一見しか取っておらず、すべてのNaNとInfで厳密にチェックしませんでした。私はあなたの2番目の合計を取り除くことができますパフォーマンスをさらに向上させることができると思う、私はちょうど今すぐに時間がありません:) –

+1

@アレックスので、私も2番目の合計を削除した、大規模な問題の場合は、よりスケーラビリティが向上します –

5

あなたの代わりにbsxfunの/ implicit expansion放送みてください:私も和の順序を変更し、さらなる改善のためにi変数を削除

x(:,1,k+1) = x(:,1,k+1)+sum(sum(A_k(:,:,2:k).*x(:,1,k-1:-1:1),3),2); 

。私のマシンとMatlab R2017bでは、L = 10000の方が約25%高速でした。

+0

@ LuisMendo:もちろんです。 25%の改善の半分は総和の順番の変更によるものです。 – horchler

+0

暗黙のバージョンは 'bsxfun'よりも少し速いようです。 – Alex

+0

@horchlerああ、私はその部分に気付かなかった –

関連する問題