how can i vectorize this for loop??
Afficher commentaires plus anciens
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 commentaire
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.
Réponse acceptée
Plus de réponses (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
le 28 Juil 2017
0 votes
2 commentaires
Jan
le 28 Juil 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
le 28 Juil 2017
Catégories
En savoir plus sur Loops and Conditional Statements dans Centre d'aide et File Exchange
Produits
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!