Optimize my for loop with vectors
1 vue (au cours des 30 derniers jours)
Afficher commentaires plus anciens
olabaz
le 28 Juil 2017
Modifié(e) : Andrei Bobrov
le 29 Juil 2017
Hi, I read that vectorizing your matlab program will speed it up so I am trying to vectorize the following for loop:
mysum = 0;
for kx = -1:dk:1
kyMax = sqrt(1^2-kx^2);
for ky = 0:dk:kyMax
myeps = kx^2 + ky^2;
mysum = mysum + myeps;
end
end
I'm not sure how to do it since {kx,ky} is not a rectangular array but rather one who's ky dimension changes depending on the kx.
0 commentaires
Réponse acceptée
Andrei Bobrov
le 28 Juil 2017
Modifié(e) : Andrei Bobrov
le 29 Juil 2017
kx = -1:dk:1;
[xx,yy] = ndgrid(0:dk:1,kx);
t = xx <= sqrt(1-kx.^2);
m = [xx(:),yy(:)];
a = m(t(:),:).^2;
out = sum(a(:));
or
kx = -1:dk:1;
B = arrayfun(@(x)0:dk:x,sqrt(1-kx.^2),'un',0);
n = cellfun(@numel,B);
out = sum(repelem(kx,n).^2 + [B{:}].^2);
2 commentaires
Chad Greene
le 28 Juil 2017
Can you explain these steps Andrei? When I try it with any value of dk I get a dimension mismatch at the t= line.
Plus de réponses (2)
Chad Greene
le 28 Juil 2017
Hi olabaz,
It looks like eps is getting overwritten each time through the loop, so you'll just end up with eps = 1. As I understand it you want eps to be a 2D matrix for all the values of kx and ky?
A minor note as an aside, eps is actually a different thing in Matlab. The way you're overwriting it works fine here, but it's probably best to avoid using that variable name.
1 commentaire
Chad Greene
le 28 Juil 2017
I really appreciate your interesting in vectorizing. It will take you far in life. First things first, 1^2 will always be 1, so we can remove a calculation by rewriting
kyMax = sqrt(1^2-kx^2);
as
kyMax = sqrt(1-kx^2);
Second, it can be helpful to get in the habit of rewriting this:
for kx = -1:dk:1
...
end
as
kx = -1:dk:1;
for k = 1:length(kx)
...
end
and then inside the loop, when you want to reference the kth value of kx, use kx(k). The difference may seem subtle, abstract, or even like an unnecessary extra step. But it means we can pull
kyMax = sqrt(1-kx^2);
out of the loop. Just calculate it once for all the values of kx. That gives us this:
mysum = 0;
kx = -1:dk:1;
kyMax = sqrt(1-kx.^2);
for k = 1:length(kx)
for ky = 0:dk:kyMax(k)
myeps = kx(k)^2 + ky^2;
mysum = mysum + myeps;
end
end
Note the .^ instead of just ^ which lets us square all the values at once. We can then do the same thing with the next for statement. That becomes this:
kx = -1:dk:1;
kyMax = sqrt(1-kx.^2);
for k = 1:length(kx)
ky = 0:dk:kyMax(k);
myeps = kx(k)^2 + ky.^2;
for kk = 1:length(ky)
mysum = mysum + myeps(kk);
end
end
and now there's really no need for that inner loop because we can just use sum. Taking out the inner loop it looks like this:
mysum = 0;
kx = -1:dk:1;
kyMax = sqrt(1-kx.^2);
for k = 1:length(kx)
ky = 0:dk:kyMax(k);
myeps = kx(k)^2 + ky.^2;
mysum = mysum + sum(myeps);
end
Already we've made some great progress because we no longer have a loop within a loop. Loops within loops have a way of slowing things down tremendously because everything within the inner loop needs to be done not just N times, but N*M times. Now I have to think about how to get rid of that other loop.
Voir également
Catégories
En savoir plus sur Loops and Conditional Statements dans Help Center et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!