Speeding up a for loop

1 view (last 30 days)
Alex Kozlov
Alex Kozlov on 12 Jan 2020
Commented: Alex Kozlov on 13 Jan 2020
Hi,
I'm trying to speed up processing time of my code.
Can the next code be reduced to be processed using vectorization instead of using a for-loop? I usually manage fine with these things, but here there are some tricky matrix operations.
Give these inputs:
S1 = 5994;
S2 = 88;
S3 = 8;
A = 100*rand(S1,S3)-50;
B = 100*rand(S2,S3)-50;
C = 100*rand(S1,S2)-50;
Const1 = 1.1;
The loop:
for vv=1:size(A,1)
temp1 = A(vv,:)-Const1*B;
temp2 = C(vv,:).*(abs(temp1).^2).';
Sum = Sum + sum(temp2,'all');
end
Sum = Sum/(S1*S3);
  1 Comment
Adam Danz
Adam Danz on 12 Jan 2020
Edited: Adam Danz on 13 Jan 2020
I assume Sum is initialized as the following (or something similar), prior to the loop.
Sum = 0;

Sign in to comment.

Accepted Answer

Thiago Henrique Gomes Lobato
If you don't mind having 3 dimensional arrays something like this can be used
rng(42)
S1 = 5994;
S2 = 88;
S3 = 8;
A = 100*rand(S1,S3)-50;
B = 100*rand(S2,S3)-50;
C = 100*rand(S1,S2)-50;
Const1 = 1.1;
Sum = 0;
tic
for vv=1:size(A,1)
temp1 = A(vv,:)-Const1*B;
temp2 = C(vv,:).*(abs(temp1).^2).';
Sum = Sum + sum(temp2,'all');
end
timeLoop = toc
% Vector alternative
tic
temp1Vec = reshape(A',1,size(A,2),size(A,1) )-Const1*B;
temp2Vec = sum(reshape(C',size(C,2),1,size(C,1)).* ((abs(temp1Vec).^2)) ,'all');
timeVec = toc
SumVec = sum(temp2Vec)/(S1*S3)
Sum = Sum/(S1*S3)
timeLoop =
0.0424
timeVec =
0.0228
SumVec =
6.6553e+03
Sum =
6.6553e+03
For your S1 I get sometimes faster results and some times slower ones, if I increase the S1 size I start to become consistent faster results.
  1 Comment
Alex Kozlov
Alex Kozlov on 13 Jan 2020
Thanks, that did the trick. I improved the speed further by replacing
((abs(temp1Vec).^2)),'all');
by:
((real(temp1Vec).^2+imag(temp1Vec).^2)),'all');
In the original code, which i couldn't share, temp1 could contain complex numbers.

Sign in to comment.

More Answers (1)

Adam Danz
Adam Danz on 12 Jan 2020
Edited: Adam Danz on 12 Jan 2020
Idea 1
This single line does the same thing as the 2nd block of your code.
Sum2 = sum(arrayfun(@(i)sum(C(i,:) .* (abs(A(i,:)-Const1*B).^2).','all'), 1:size(A,1)))/(S1*S3);
isequal(Sum,Sum2) % Test that it matches the loop output (it does)
However, it's 0.01sec longer than your loop method.
Idea 2
Even if your loop is condensed by combining the variables, the improvement in speed is barely measurable and it comes at the expense of readability.
Sum2 = 0;
for vv=1:size(A,1)
Sum2 = Sum2 + sum(C(vv,:) .* (abs(A(vv,:)-Const1*B).^2).', 'all');
end
Sum2 = Sum2/(S1*S3);
isequal(Sum,Sum2) % Test that it matches the loop output (it does)

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Products


Release

R2019a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!