2

Bsize9x100x51Ksizeの 2 つの行列があります34x9x100。sizeの最終的な行列が得られるように、すべてのK(34)を のそれぞれで乗算したいと考えています。B(9)G34x9x100x51

例: 要素G(:,5,60,25)は次のように構成されます。

G(:,5,60,25)=K(:,5,60)*B(5,60,25).

この例が、私が何をしたいのかを理解するのに役立つことを願っています。ありがとうございました

4

2 に答える 2

3

matlabでネストされたループを記述していることに気付いたときはいつでも、組み込みのベクトル化された形式の関数を使用してかなり高速化できる可能性があります。通常、コードもかなり短くなります(ただし、読者にはすぐにはわかりにくいことが多いので、コードにコメントを付けてください)。

この場合、ネストされたループを回避することで違いはありますか?絶対!仕事に取り掛かりましょう。@slaytonは3ループソリューションを提供しています。私たちはより速くなることができます。

問題を少し言い換えると、B51個の9x100行列とK34個の9x100行列があります。の組み合わせごとに、とからのそれぞれの行列51x34を要素ごとに乗算します。9x100BK

要素ごとの乗算は、にとって素晴らしい仕事です。したがって、この問題を2つの次元(の3次元、の1次元)bsxfunに沿って作業するように概念的に減らすことができます。BK

最初の2ループソリューション:

B = rand(9,100,51);
K = rand(34,9,100);
G = nan(34,9,100,51);

for b=1:size(B,3)
    for k=1:size(K,1)
        G(k,:,:,b) = bsxfun(@times,B(:,:,b), squeeze(K(k,:,:)));
    end
end

OK、2つのループが進行中です。もっと上手くできますか?さて、行列BKは適切な次元に沿って複製でき、要素ごとに一度に乗算できることを認識しましょう。

B = rand(9,100,51);
K = rand(34,9,100);

B2 = repmat(permute(B,[4 1 2 3]), [size(K,1) size(B)]);
K2 = repmat(K, [size(K) size(B,3)]);

G = bsxfun(@times,B2,K2);

では、ソリューションは速度的にどのように比較されますか?私はオクターブオンラインユーティリティでテストしましたが、イニシャルBKマトリックスを生成する時間は含まれていませんでした。G事前割り当てが必要なソリューションのマトリックスを事前に割り当てる時間を含めました。コードは以下のとおりです。

3ループ(@slaytonの回答):4.024471 s
2ループソリューション:1.616120s0
ループrepmat/bsxfunソリューション:1.211850s0
ループrepmat/bsxfunソリューション、一時的なし:0.605838 s

警告:タイミングはマシンによってかなり異なる場合があります。優れたタイミングテストのためのオンラインユーティリティは信頼できません。ループが実行されたときの順序を変更すると(変数を再利用しないように注意し、割り当ての時間を混乱させないように注意しても)、状況が少し変わりました。つまり、2ループのソリューションは、一時的なものが格納されたループなしのソリューションと同じくらい高速でした。ただし、ベクトル化が進むほど、より良い結果が得られます。

速度テストのコードは次のとおりです。

B = rand(9,100,51);
K = rand(34,9,100);

tic
G1 = nan(34,9,100,51);

for ii = 1:size(B,1)
  for jj = 1:size(B,2);
    for kk = 1:size(B,3)
      G1(:, ii, jj, kk) = K(:,ii,jj) .* B(ii,jj,kk);
    end
  end
end
t=toc;
printf('Time for 3 loop solution: %f\n' ,t)

tic
G2 = nan(34,9,100,51);

    for b=1:size(B,3)
        for k=1:size(K,1)
            G2(k,:,:,b) = bsxfun(@times,B(:,:,b), squeeze(K(k,:,:)));
        end
    end
t=toc;
printf('Time for 2 loop solution: %f\n' ,t)
tic

B2 = repmat(permute(B,[4 1 2 3]), [size(K,1) 1 1 1]);
    K2 = repmat(K, [1 1 1 size(B,3)]);

    G3 = bsxfun(@times,B2,K2);
t=toc;
printf('Time for 0-loop repmat/bsxfun solution: %f\n' ,t)

tic

    G4 = bsxfun(@times,repmat(permute(B,[4 1 2 3]), [size(K,1) 1 1 1]),repmat(K, [1 1 1 size(B,3)]));
t=toc;
printf('Time for 0-loop repmat/bsxfun solution, no temporaries: %f\n' ,t)


disp('Are the results equal?')
isequal(G1,G2)
isequal(G1,G3)

Time for 3 loop solution: 4.024471
Time for 2 loop solution: 1.616120
Time for 0-loop repmat/bsxfun solution: 1.211850
Time for 0-loop repmat/bsxfun solution, no temporaries: 0.605838
Are the results equal?
ans =  1
ans =  1    
于 2013-02-27T06:26:45.123 に答える
0

ネストされたループでこれを行うことができますが、おそらくそれほど高速ではありません。

B = rand(9,100,51);
K = rand(34,9,100);

G = nan(34,9,100,51)

for ii = 1:size(B,1)
  for jj = 1:size(B,2);
    for kk = 1:size(B,3)
      G(:, ii, jj, kk) = K(:,ii,jj) .* B(ii,jj,kk);
    end
  end
end

長い一日だったので、私の脳は少し揚げられています。これを改善できる人を称賛します!

于 2013-02-27T01:02:56.410 に答える