0

有限要素を使用して、2d 長方形のポアソン方程式の解をコーディングしています。コードを単純化するために、基底関数へのハンドルを配列に格納し、これらの基底関数をループして、行列と右辺を作成します。これに関する問題は、非常に粗いグリッドの場合でも、法外に遅いことです。9x9 グリッド (ディリクレ BC を使用すると、解決するノードが 49 あります) の場合、約 20 秒かかります。プロファイルを使用して、約半分の時間が基底関数へのアクセス (実行ではない) に費やされていることに気付きました。

プロファイラーによるmatrix_assembly>@(x,y)bilinearBasisFunction(x,y,xc(k-1),xc(k),xc(k+1),yc(j-1),yc(j),yc(j+1)) (156800 calls, 11.558 sec)と、自己時間 (双一次基底コードを実行していない) は 9 秒を超えています。なぜこれがとても遅いのかについてのアイデアはありますか?

コードの一部を次に示します。必要に応じてさらに投稿できます。

%% setting up the basis functions, storing them in cell array
basisFunctions = cell(nu, 1); %nu is #unknowns 
i = 1;
for j = 2:length(yc) - 1
for k = 2:length(xc) - 1
    basisFunctions{i} = @(x,y) bilinearBasisFunction(x,y, xc(k-1), xc(k),...
        xc(k+1), yc(j-1), yc(j), yc(j+1)); %my code for bilinear basis functions
    i = i+1;
end
end

%% Assemble matrices and RHS
M = zeros(nu,nu);
S = zeros(nu,nu);
F = zeros(nu, 1);

for iE = 1:ne
for iBF = 1:nu
    [z1, dx1, dy1] = basisFunctions{iBF}(qx(iE), qy(iE));

    F(iBF) = F(iBF) + z1*forcing_handle(qx(iE),qy(iE))/ae(iE);

    for jBF = 1:nu
        [z2, dx2, dy2] = basisFunctions{jBF}(qx(iE), qy(iE));

        %M(iBF,jBF) = M(iBF,jBF) + z1*z2/ae(iE);
        S(iBF,jBF) = S(iBF, jBF) + (dx1*dx2 + dy1*dy2)/ae(iE);
    end        
end
end
4

1 に答える 1

0

basisFunctionsセル配列から通常の配列に変更してみてください。

bilinearBasisFunctionを使用するのではなく、jBF ループ内で直接呼び出しをインライン化することもできますbasisFunctions。Matlab で無名関数を作成して後で使用すると、ターゲット関数を直接使用するよりも常に遅くなります。この方法では、コードが少し冗長になる可能性がありますが、より高速になります。

于 2013-11-21T09:29:59.570 に答える