2013年4月7日日曜日

MATLABのループ メモ

今日は久々にMATLABでコードを書こうと思いたった。
fortran77でよく使われているプログラムがあるのだけど、それをもっと楽に使用するため。

しかし、適当にMATLABでコードを書くと、変なloopを書いてしまいそうで怖い。
で、行列の掛け算のやり方と速度を確認したのでメモしておく。

単純なfor loopと、MATLAB特有のドット演算子を使ったものと、さらに添字にしたらどうなるかな、というもの。

結果は、当然だけどドット演算子を使わないとめちゃくちゃ遅い。あと、添字をつけたらfor loopより遅くなってしまった。使い方がまずいんだろうか。
あと、構造体を絡めて計算する場合は、構造体配列にすると遅くなるので、構造体に配列を入れてしまうのが良いみたい。
for loop: y(i) = x(i) * x(i);
Elapsed time is 0.015437 seconds.

vectorized loop: y = x .* x
Elapsed time is 0.002330 seconds.

vectorized loop2: y(1:n) = x(1:n) .* x(1:n)
Elapsed time is 0.021473 seconds.

using struct: y = s.x .* x
Elapsed time is 0.003305 seconds.

構造体のフィールドに配列を入れた場合と、構造体配列を使った場合を比較すると、構造体配列はアクセスがとんでもなく遅いよう。
ということで、構造体を作るときは注意しなければいけないな。使い方が悪いだけかもしれないけども。しかし、こんなに遅くなるとは思わなかった。
using struct: y = s.x .* x
Elapsed time is 0.000005 seconds.

using struct (for loop): y = s2.x .* x
Elapsed time is 0.000239 seconds.

using struct (index): y = s2.x .* x
Elapsed time is 0.001868 seconds.
使ったコードは下記のもの。

clear all;
n = 1000000;

s = struct('x', ones(1,n));
x = 2 * ones(1,n);
y = zeros(1,n);

% for loop
disp('for loop: y(i) = x(i) * x(i);');
tic
for i = 1:n
    y(i) = x(i) * x(i);
end
toc

% vectorized loop
disp('vectorized loop: y = x .* x');
tic
y = x .* x;
toc

% vectorized loop?
disp('vectorized loop2: y(1:n) = x(1:n) .* x(1:n)');
tic
y(1:n) = x(1:n) .* x(1:n);
toc

% vectorized loop using structure
disp('using struct: y = s.x .* x');
tic 
y = s.x .* x;
toc


clear all;
n = 1000;

s = struct('x', ones(1,n));  % s.x(1:n) のようにs.xに配列を指定
s2(1:n) = struct('x', 1);    % s(1:n).x のように構造体の配列
y = zeros(1,n);

disp('using struct: y = s.x .* x');
tic 
y = s.x .* x;
toc

disp('using struct (for loop): y = s2.x .* x');
tic 
s2_x = zeros(1,n);
for i = 1:n
    s2_x(i) = s2(i).x;
end
y = s2_x .* x;
toc

disp('using struct (index): y = s2.x .* x');
tic 
s2_x = zeros(1,n);
s2_x = s2(1:n).x;
y = s2_x .* x;
toc

0 件のコメント:

コメントを投稿