行列演算のススメ

[Octave]

Octave と MATLAB に共通して言える高速化の手法は、for 文を書くな!! です。人生は for 文を書くには短すぎる...。

組み込み関数を使って for文をなくす

n = 1;
wns = randn(100000, 1);
for k=1:length(wns)
   if wns(k) > a
      idx(n) = k;
      n = n+1;
   end
end
のコードを、
wns = randn(100000, 1);
idx = find(wns > a);

と書き直せば格段に速くなります。

配列を駆使してfor文をなくす例

for t=1:1000
   sig(t) = sin(2*pi*100*t/sf);
end
を、
t = 1:1000;
sig = sin(2*pi*100*t/sf);
とします。もちっと高度な例は、
f = 100:10:2000;
t = (1:1000)/sf;
for k=1:length(f)
   sig(k,:) = sin(2*pi*f(k)*t);
end
を、
f = 100:10:2000;
ff = ones(length(f), 1).*f';
t = (1:1000)/sf;
sig = sin(2*pi*t*ff*t);
です。(M x 1) x (1 x N) = (M x N) 行列計算の公式を思い出しましょう:-)。 ちなみに、この例では、約 length(f)倍メモリを多く使用するので、メモリが 少ない場合は HDDへのスワップガリガリでチョー遅くなる場合もあるので、要 注意。

MATLAB & Octave らしいスゴい表現

場合分けがある時には、

for k=1:10000
   if x(k) > 2
      y(k) = x(k)^2+5;
   elseif x(k) < -2
      y(k) = x(k)^3-5; 
   else
      y(k) = x(k);
   end
end
を、
y = (x > 2).*(x.^2+5) + (x < -2).*(x.^3-5) + (x <= 2 & x >= -2).*x;
なんて書けちゃうので、モウ大変!!。

akira@rsch.tuis.ac.jp