Optimize my for loop with vectors
1 visualización (últimos 30 días)
Mostrar comentarios más antiguos
olabaz
el 28 de Jul. de 2017
Editada: Andrei Bobrov
el 29 de Jul. de 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 comentarios
Respuesta aceptada
Andrei Bobrov
el 28 de Jul. de 2017
Editada: Andrei Bobrov
el 29 de Jul. de 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 comentarios
Chad Greene
el 28 de Jul. de 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.
Más respuestas (2)
Chad Greene
el 28 de Jul. de 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 comentario
Chad Greene
el 28 de Jul. de 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.
Ver también
Categorías
Más información sobre Loops and Conditional Statements en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!