質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
MATLAB

MATLABはMathWorksで開発された数値計算や数値の視覚化のための高水準の対話型プログラミング環境です。

Q&A

2回答

1172閲覧

コードの高速化の方法を知りたいです。

volgung

総合スコア0

MATLAB

MATLABはMathWorksで開発された数値計算や数値の視覚化のための高水準の対話型プログラミング環境です。

0グッド

0クリップ

投稿2021/09/28 03:55

前提・実現したいこと

matlabにて、401×401の行列を使用した計算を行うプログラムを作っています。
このプログラムの実行時間を短縮、コードの高速化を行いたいです。
ここに質問の内容を詳しく書いてください。

しかし、実行において相当の時間がかかってしまいます。matlab初心者のため、ベクトル化などの方法があると知りはしたのですがいまいち使い方がわかりません。

発生している問題・エラーメッセージ

時間が長い。。。

該当のソースコード

%逆問題とく %最急降下法 clear tic %再現音場をあらかじめ計算 %定数定義 f = 1000; %周波数 ← 色々と変えてみてください。100 Hz ~ 10 kHz くらいの範囲で w = 2*pi*f; %角周波数 %Vo = 0.2; %体積速度 (m^3/s) rho = 1.293; %空気密度 c = 340; %音速 k = w/c; %波数 % l = 0.1; l = 0; % 音源面 xmin1 = -4; xmax1 = 4; % ymin = -0.5; % ymax = 0.5; zmin1 = 0.1; zmax1 = 10; %観測面(z=l平面とする)での音圧を求める x1 = xmin1:0.02:xmax1; z1 = zmin1:0.02:zmax1; %音源位置をz=-2に移動 %Voのみ後からかける p = @(xmat, ymat, zmat, x_1, y_1) (1j * w * rho * exp(-1j * k * sqrt((xmat-x_1) .^ 2+(ymat-y_1) .^ 2+ (zmat+2) .^ 2))) ... ./ (2*pi*sqrt((xmat-x_1) .^ 2+(ymat-y_1) .^ 2 + (zmat+2) .^ 2)); p_r_xy = 0; p_r_xz = 0; xmin0 = -0.5; xmax0 = 0.5; ymin0 = -0.5; ymax0 = 0.5; %0.5刻みはできる,0.1刻みから x0 = xmin0:0.0025:xmax0; y0 = ymin0:0.0025:ymax0; % z = l における X-Y 面 [xmat1, ymat1] = meshgrid(x0, y0); % y = 0 における X-Z 面 %[xmat2, zmat2] = meshgrid(x1, z1); %体積速度行列 a = 0.1; b = 0.5; Vo = a+(b-a).*rand(size(xmat1,1)); for x_1 = xmin0 : 0.1 : xmax0 for y_1 = ymin0 : 0.1 : ymax0 % p = @(xmat, ymat, zmat) (1j * w * rho * Vo * exp(-1j * k * sqrt((xmat-x_1) .^ 2+(ymat-y_1) .^ 2+ zmat .^ 2))) ... % ./ (2*pi*sqrt((xmat-x_1) .^ 2+(ymat-y_1) .^ 2 + zmat .^ 2)); % p_r_xy = p_r_xy + p(xmat, ymat, l); p_r_xy = p_r_xy + p(xmat1, ymat1, l, x_1, y_1) .* Vo; end end %---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- %ここから逆問題について最急降下法の実装を試みる %定数定義 sz = size(p_r_xy); %Vo = ones(sz); %重み1 %Vo1 = 0.1; a = 0.0000001; %学習率 %予測値の計算 %xy平面での差をなくすように重みw1を変更していく p_f = @(xmat, ymat, zmat, x_1, y_1)(1j * w * rho * exp(-1j * k * sqrt((xmat-x_1) .^ 2+(ymat-y_1) .^ 2+ (zmat+2) .^ 2)))... ./(2 * pi * sqrt((xmat-x_1) .^ 2+(ymat-y_1) .^ 2 + (zmat+2) .^ 2)); %w1の偏微分 dw1 = @(xmat, ymat, zmat, x_1, y_1)(1j * w * rho * exp(-1j * k * sqrt((xmat-x_1) .^ 2+(ymat-y_1) .^ 2+ (zmat+2) .^ 2)))... ./(2 * pi * sqrt((xmat-x_1) .^ 2+(ymat-y_1) .^ 2 + (zmat+2) .^ 2)); %偏微分の値が今回一定のためここで計算 s = dw1(xmat1, ymat1 , l, x_1, y_1); %p_r_xyの行数r、列数q r = size(p_r_xy,1); q = size(p_r_xy,2); %与える体積速度(最適化前の体積速度)(初期値) vo = 100; Vo_1 = repmat(vo,r,q); %目標との差Lの指定 Lmax = 50; %最適化されるまで無限ループ L = zeros(r,q); B = zeros(r,q); while 1 p_r_xy_f = zeros(r,q); for x_1 = xmin0:0.1:xmax0 for y_1 = ymin0:0.1:ymax0 p_r_xy_f = p_r_xy_f + p_f(xmat1, ymat1, l, x_1, y_1) .* Vo_1; end end %目標との差 L = real(p_r_xy - p_r_xy_f); %最適化のための条件分岐 B = abs(L) > Lmax; if all(B == 0) break elseif nnz(B)~=0 for i = 1 : 1 : r for j = 1 : 1 : q Vo_1(i,j)=(real(s(i,j)) > 0).*(Vo_1(i,j) + a * real(s(i,j)) * L(i,j)) + (real(s(i,j)) < 0).*(Vo_1(i,j) - a * real(s(i,j)) * L(i,j)); end end end end toc

試したこと

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jbpb0

2021/09/28 04:04

コード全体の時間だけではなく、どこでどれだけ時間がかかってるかも測りましょう
volgung

2021/09/28 04:13

申し訳ありません。少なくとも15分以上の時間がかかっており、正確に計測しておりませんが、終盤のwhile文までは0.3秒弱で到達しているため、whileの中身に相当の時間がかかっていると思われます。
guest

回答2

0

while以下が大部分を占めているようなので、while文の中のみ見ましたが、

単にプログラム的には
・最初のforループはwhileの外(前)に出せるのでは。
・if文の中のforループはベクトル処理できるのでは。
と思います。
(以下に変更した部分の例を載せます)
これにより、whileループ1回当たりの所要時間は小さくなるはずです。

ただ、計算時間は、終了の条件(all(B == 0))次第で変わるので、
whileループが無限ループになっている場合は、これではどうにもなりませんが。


p_r_xy_f0 = zeros(r,q);

for x_1 = xmin0:0.1:xmax0
for y_1 = ymin0:0.1:ymax0
p_r_xy_f0 = p_r_xy_f0 + p_f(xmat1, ymat1, l, x_1, y_1) ;
end
end

while 1
p_r_xy_f = p_r_xy_f0.* Vo_1;

%目標との差 L = real(p_r_xy - p_r_xy_f); %最適化のための条件分岐 B = abs(L) > Lmax; if all(B == 0) break else Vo_1=(real(s) > 0).*(Vo_1 + a * real(s) .* L) + (real(s) < 0).* (Vo_1- a * real(s) .* L); end

end

投稿2021/10/05 02:59

shin4

総合スコア11

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

このままでは丸投げとしか言えませんので、まずは時間がかかっているという式を簡単にし、それぞれの変数の内容を回答者にわかるようにしましょう。

また、matlabではi, jは虚数の意味ですので、添字には使わないようにしましょう。特にこのプログラムでは実際にi, jを虚数の意味で使っているのでアウトです。

投稿2021/09/29 00:53

yuki23

総合スコア1448

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問