how can i vectorize this for loop??
Show older comments
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 Comment
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.
Accepted Answer
More Answers (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
on 28 Jul 2017
0 votes
2 Comments
Jan
on 28 Jul 2017
@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
on 28 Jul 2017
Categories
Find more on Loops and Conditional Statements in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!