1

私の MATLAB コードを高速化するためにあなたの助けが必要です。ライン 17 は最も高価な部品です。これは、2 つのネストされたループが原因です。ループを削除して、それを 1 つの行列乗算式に書き直すのに助けが必要です。セルとして dKdx を使用しているため、ネストされたループを単純な行列乗算項に置き換えるという問題が発生していることに注意してください。何か案は?以下は簡略化したコードです。dKdx はセルである必要はないのでしょうか? cell の背後にあるアイデアは、[2*(nelx+1) (nely+1),2 (nelx+1)*(nely+1)]のサイズの行列をたくさん格納できるようにすることでした。

    clc
    nelx = 16; nely = 8;
    dKdx = cell(2*(nelx+1)*(nely+1),1);
    Hess = zeros(nelx*nely,nelx*nely);
    U = rand(2*(nelx+1)*(nely+1),1);
    dUdx = rand(2*(nelx+1)*(nely+1),nelx*nely);

    for elx = 1:nelx
        for ely = 1:nely
            elm = nely*(elx-1)+ely;               
            dKdx{elm,1} = rand(2*(nelx+1)*(nely+1),2*(nelx+1)*(nely+1));
        end
    end

    for i = 1:nelx*nely    
        for j = i:nelx*nely
            Hess(i,j) = U'*dKdx{j,1}*dUdx(:,i);
            if i ~= j
                Hess(j,i) = Hess(i,j);
            end
        end
    end
4

2 に答える 2

3

これを取得する方法の 1 つを次に示します。

  B = reshape(U'*cell2mat(dKdx'),[size(U,1) nelx*nely]);
  C = B'*dUdx;
  Hess=tril(C)+triu(C',1);

私のマシンでは、このコードは for ループよりも 6 ~ 7 倍高速に実行されます。他にもっと速い方法があるのだろうか...

于 2012-10-18T00:41:05.887 に答える
2

ヘッセ行列がボトルネックであることは驚くべきことではないかもしれません。O(n ^ 2)行列要素を計算する必要があり、行列要素ごとにO(n ^ 3)作業を行っているため、行列を反転するよりも悪いO(n ^ 5)になります(誤解しない限りコード)。

dKdx{j,1}*dUdx(:,i)そうは言っても、内側のループの行列/ベクトルの乗算を外側のループの単一の行列/行列の乗算に置き換えてから、内側のループでdKdx{j,1}*dUdx必要な特定の列を引き出すことができるはずです(最初にもする必要がありjます)。私は今これを自分で試す時間がありませんが、おそらくそれはあなたを助けるでしょう。

別の考え:行列の乗算の数を減らすために利用できる構造が行列にないことを確認しますか?

アップデート

私のアイデアを機能させる過程で、私は次のことを思いつきました。

Hess2 = zeros(nelx*nely,nelx*nely);
for j=1:nelx*nely
    Hess2(j,:) = U'*dKdx{j,1}*dUdx;
end
Hess2 = tril(Hess2)+triu(Hess2',1);

私のマシンでは、これは25倍高速ですが、ネイトは80倍高速なので、彼は私を打ち負かします。

于 2012-10-17T23:19:36.117 に答える