how can i vectorize this for loop??
古いコメントを表示
clc;
clear all;
close all;
k = 1:0.5:10;
a = 1:0.5:5;
n1 = numel(k);
nump = kron(k,ones(1,length(a)))';
denp = repmat([ones(n2,1), a.', zeros(n2,1)] ,n1, 1);
w=[0.1,0.5,0.8,1,2,8,15,50,100];
n2 = numel(a);
delay=0;
[rn,cn]=size(nump);
[rd,cd]=size(denp);
[rw,cw]=size(w);
[rdel,cdel]=size(delay);
if rw>1,
w = w(:)';
end
if rn~=rd & (rn~=1 & rd~=1),
end
if rdel~=rn & rdel~=rd & rdel~=1,
end
i=sqrt(-1);
s=i*w;
mx = max(rn,rd);
q=1; r=1;
for h=1:mx,
q=(rn>1)*h+(rn==1); r=(rd>1)*h+(rd==1); d=(rdel>1)*h+(rdel==1);
upper = polyval(nump(q,:),s);
lower = polyval(denp(r,:),s);
cp(h,:)=(upper./lower).*exp(-s*delay(d));
end
toc
1 件のコメント
You need to resort the code lines: n2 is used before it is defined. The toc is useless without a tic. Omit the darn clear all, because it removes all loaded functions from the memory. The reloading from disk wastes time and interfer with measuring the run time.
i=sqrt(-1) is useless, because this is the definition of "i" already.
Omit the useless code
if rn~=rd & (rn~=1 & rd~=1),
end
if rdel~=rn & rdel~=rd & rdel~=1,
end
except if you want to confuse the readers.
採用された回答
その他の回答 (2 件)
Now the vectorized version:
function cp = YourFcn()
k = 1:0.5:10;
a = 1:0.5:5;
n1 = numel(k);
nump = kron(k, ones(1, length(a)))';
n2 = numel(a);
denp = repmat([ones(n2,1), a.', zeros(n2,1)], n1, 1);
w = [0.1,0.5,0.8,1,2,8,15,50,100];
delay = 0;
w = w(:)';
s = 1i * w;
upper = nump(:, 1);
for i = 2:size(nump, 2)
upper = s .* upper + nump(:, i); % requires >= R2016b !!!
end
lower = denp(:, 1);
for i = 2:size(denp, 2)
lower = s .* lower + denp(:, i); % requires >= R2016b !!!
end
cp = (upper ./ lower) .* exp(-s * delay); % requires >= R2016b !!!
end
:-) Nice. 0.023 seconds. 4 times faster than the efficient loop.
If you run this on older Matlab versions, you need some bsxfun() calls:
...
s = 1i * w;
upper = nump(:, 1);
for i = 2:size(nump, 2)
upper = bsxfun(@plus, bsxfun(@times, s, upper), nump(:, i));
end
lower = denp(:, 1);
for i = 2:size(denp, 2)
lower = bsxfun(@plus, bsxfun(@times, s, lower), denp(:, i));
end
cp = bsxfun(@times, bsxfun(@rdivide, upper, lower), exp(-s * delay));
While this code is compact and efficient, exhaustive comments are required to recognize, that this is a vectorized Horner scheme from polyval.
Note that the vectorized code does not need the case differentiation for rn>1, rd>1 and del>1 and that the number of exp() calls is reduced to the required minimum automatically.
I hope the real problem is much larger. Otherwise the absolute speed up is only some milliseconds from 0.0046 to 0.00023. For the inputs:
k = 1:0.05:10;
a = 1:0.05:5;
the original version needs 217, the efficient loop 8 and the vectorized code 1.06 seconds. And they even reply the same values ;-)
nelson
2017 年 7 月 28 日
0 投票
2 件のコメント
Jan
2017 年 7 月 28 日
@nelson: Please post comments as comments. When you use the section for answers, it is not clear to which answer they belong to. If you mean the Horner scheme:
upper = nump(:, 1);
for i = 2:size(nump, 2)
upper = s .* upper + nump(:, i);
end
No, this cannot be vectorized furtherly. Remember that the Horner scheme is known for its numerical stability and efficiency.
If you still need more speed, hire a programmer to create a fast C-Mex function.
nelson
2017 年 7 月 28 日
カテゴリ
ヘルプ センター および File Exchange で Loops and Conditional Statements についてさらに検索
製品
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!