Is it possible to speed up this loop or avoid from using?
Show older comments
I give an example code below including 4 loops. How can I speed up this procedure? thanks for any help and ideas.
clc;clear all
%%inputs
dx=1; dy=1; xo=5;
f1=5;
f2=10;
f3=15;
kx=1:50;
ky=1:50;
k=rand(50,50);
z=rand(50,50);
%%%
%%%% how can I improve this example below for running faster ?
tic
for j=1:50
for i=1:50
total=0;
for m=1:50
beta= (m-1)*dy;
for n=1:50
alpha= (n-1)*dx;
f4 =(1-exp(-(xo+ 2.*pi.*k(j,i)).*z(m,n)));
f5 = exp(-2.*pi.*(kx(i).*alpha + ky(j).*beta));
total = total+ f1.*f2.*f3.*f4.*f5;
end
end
L(j,i)=total;
end
end
toc
3 Comments
darova
on 29 May 2019
Maybe you have source formula or something?
e_oksum
on 29 May 2019
If speed matters, the first thing you should do is to remove the clear all. The editor marks the line "L(j,i) = total" with an orange line and explains, that the iterative growing of an array wastes time. So pre-allocate before the loop:
L = zeros(50, 50)
But this does not influence the runtime substantially in this case.
Accepted Answer
More Answers (1)
Start with vectorizing the innermost loop:
dx = 1; dy = 1; xo = 5;
f1 = 5;
f2 = 10;
f3 = 15;
kx = 1:50;
ky = 1:50;
k = rand(50,50);
z = rand(50,50);
tic
L = zeros(50, 50); % Pre-allocate
for j = 1:50
for i = 1:50
total = 0;
for m = 1:50
beta = (m-1) * dy;
% for n = 1:50
alpha = ((1:50)-1)*dx;
f4 = (1-exp(-(xo + 2.*pi.*k(j,i)) .* z(m, 1:50)));
f5 = exp(-2 * pi * (kx(i) * alpha + ky(j) .* beta));
total = total + sum(f4 .* f5);
% end
end
L(j, i) = f1 * f2 * f3 * total;
end
end
toc
This reduces the runtime from 62 to 2 seconds already. Do you see, how it works? I just moved the index vector from for n = 1:50 inside the code by replacing all "n" by "1:50". I've moved the constant f1 * f2 * f3 out of the loop - actually it could be multiplied outside all loops also. In addition a sum() is needed around f4 .* f5.
Now do the same for for m also:
tic
L = zeros(50, 50); % Pre-allocate
for j = 1:50
for i = 1:50
total = 0;
% for m = 1:50
beta = ((1:50).'-1) * dy;
% for n = 1:50
alpha = ((1:50)-1)*dx;
f4 = (1-exp(-(xo + 2.*pi.*k(j,i)) .* z(1:50, 1:50)));
f5 = exp(-2 * pi * (kx(i) * alpha + ky(j) .* beta));
total = total + sum(sum(f4 .* f5));
% end
% end
L(j, i) = f1 * f2 * f3 * total;
end
end
toc
Now the index vector for beta must be transposed and for f5 the auto-expanding is applied.
This needs 0.22 seconds. With some simplifications and moving the definitions of alpha and beta before the loops:
L = zeros(50, 50); % Pre-allocate
alpha = (0:49) * dx;
beta = (0:49).' * dy;
for j = 1:50
for i = 1:50
f4 = (1 - exp(-(xo + 2 * pi * k(j,i)) .* z));
f5 = exp(-2 * pi * (kx(i) * alpha + ky(j) .* beta));
% For Matlab < R2018b without auto-expanding:
%f5 = exp(-2 * pi * (bsxfun(@plus, kx(i) * alpha, ky(j) .* beta)));
L(j, i) = sum(sum(f4 .* f5));
end
end
L = f1 * f2 * f3 * L;
0.17 seconds.
Now it's time to use some maths: exp(a + b) = exp(a) .* exp(b). Because the exp() function is very expensive, it is much cheaper to evaluate it for the two vectors instead of the matrix:
L = zeros(50, 50); % Pre-allocate
alpha = (0:49) * dx;
beta = (0:49).' * dy;
for j = 1:50
for i = 1:50
f4 = (1 - exp(-(xo + 2 * pi * k(j,i)) .* z));
% f5 = exp(-2 * pi * (kx(i) * alpha + ky(j) .* beta));
f5 = exp(-2 * pi * kx(i) * alpha) .* exp(-2 * pi * ky(j) .* beta);
L(j, i) = sum(sum(f4 .* f5));
end
end
L = f1 * f2 * f3 * L;
0.14 seconds. But the 2nd part of the f5 calculations does not depend on the inner loop, so move it outside:
L = zeros(50, 50); % Pre-allocate
alpha = (0:49) * dx;
beta = (0:49).' * dy;
for j = 1:50
f5_j = exp(-2 * pi * ky(j) .* beta);
for i = 1:50
f4 = (1 - exp(-(xo + 2 * pi * k(j,i)) .* z));
% f5 = exp(-2 * pi * (kx(i) * alpha + ky(j) .* beta));
f5 = exp(-2 * pi * kx(i) * alpha) .* f5_j;
L(j, i) = sum(sum(f4 .* f5));
end
end
L = f1 * f2 * f3 * L;
0.12 seconds. I hoped it is faster.
Now the next performance boost is to vectorize the outer loops also: See Matt J's answer.
Categories
Find more on Loops and Conditional Statements in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!