Vectorization of For loop
Mostrar comentarios más antiguos
Dear Matlab community,
Is it possible to vectorize the following for loop:
a = rand(100,100);
b = rand(500,100,100);
for i = 1:500
c = reshape(b(i, :, :),100,100);
d(i) = sum(sum(a.*c));
end
14 comentarios
MahdiH
el 14 de Ag. de 2020
Bruno Luong
el 14 de Ag. de 2020
Editada: Bruno Luong
el 14 de Ag. de 2020
I get different tic/toc results. Check if you have enough RAM, this code requires > 6Gb (my laptop have 16 Gb)
function benchtest
a = rand(1000,1000);
b = rand(500,1000,1000);
%%
tic
d = zeros(1,500);
for i = 1:500
c = reshape(b(i, :, :),1000,1000);
d(i) = sum(sum(a.*c));
end
toc % Elapsed time is 12.940297 seconds.
%% Walter answer:
tic
d = sum(b .* reshape(a, 1, 1000, 1000), [2 3]);
toc % Elapsed time is 1.453960 seconds.
%%%%%%%%
%% Bruno answer:
tic
d = b(:,:)*a(:);
toc % Elapsed time is 2.399184 seconds.
MahdiH
el 15 de Ag. de 2020
Walter Roberson
el 15 de Ag. de 2020
MATLAB Online test using Bruno's code
Elapsed time is 11.686848 seconds. Elapsed time is 0.881116 seconds. Elapsed time is 2.748569 seconds.
Walter Roberson
el 15 de Ag. de 2020
d = sum(sum(a.*b))/sqrt(sum(sum(a.*a))*sum(sum(b.*b)));
You need to index b there, and probably squeeze()
parts can be pulled out of the loop.
MahdiH
el 15 de Ag. de 2020
Walter Roberson
el 15 de Ag. de 2020
a = rand(1000,1000);
b = rand(500,1000,1000);
a2sumsqrt = sqrt(sum(a(:).*a(:)));
for i = 1:500
B = squeeze(b(i,:,:));
b2sumsqrt = sqrt(sum(B(:).*B(:)));
d(i) = sum(a(:).*B(:))/(a2sumsqrt/b2sumsqrt);
end
And from there you can go to
a = rand(1000,1000);
b = rand(500,1000,1000);
a2sumsqrt = sqrt(sum(a.*a, [1 2]));
b2sumsqrt = sqrt(sum(b.*b, [2 3]));
for i = 1:500
B = squeeze(b(i,:,:));
d(i) = sum(a(:).*B(:))/(a2sumsqrt/b2sumsqrt(i));
end
and you can do better than that too.
Bruno Luong
el 15 de Ag. de 2020
"@ Bruno, my laptop has 8 Gb of RAM. Is it possible with such RAM to speed up the following simple code; knowing that my laptop can finish this for loop in about 20 sec. "
It's no longer the RAM speed. I think my code and Walter code requires some big copy of extra temporary array and your computer (has barely enough memory) starts to swap the RAM to the hard drive that slows down the runtime.
Your code however requires only a small chunk extra of memory and it can run entirely without swapping onto HD.
Bruno Luong
el 15 de Ag. de 2020
Editada: Bruno Luong
el 15 de Ag. de 2020
Your code bellow doesn't run
a = rand(1000,1000);
b = rand(500,1000,1000);
for i = 1:500
d(i) = sum(sum(a.*b(i,:,:)))/sqrt(sum(sum(a.*a))*sum(sum(b(i,:,:).*b(i,:,:))));
end
I guess you want to do this
function benchtest
a = rand(1000,1000);
b = rand(500,1000,1000);
%% Walter answer fixed error "/" -> '*'
tic
a2sumsqrt = sqrt(sum(a(:).*a(:)));
for i = 1:size(b,1)
B = squeeze(b(i,:,:));
b2sumsqrt = sqrt(sum(B(:).*B(:)));
d(i) = sum(a(:).*B(:))/(a2sumsqrt*b2sumsqrt);
end
toc % Elapsed time is 14.231275 seconds.
%%%%%%%%
%% Bruno answer:
tic
b2 = b(:,:);
a2 = a(:);
d = ((b2*a2) ./ sqrt(sum(b2.^2,2))) / norm(a2);
toc % Elapsed time is 3.586152 seconds.
end
MahdiH
el 15 de Ag. de 2020
Bruno Luong
el 15 de Ag. de 2020
You seem to mistaken between me and Walter, I gave the explanation of RAM issue.
MahdiH
el 15 de Ag. de 2020
Bruno Luong
el 15 de Ag. de 2020
You could do a hybrid method: for-loop with each iteration compute a chunk of 50 elements of d.
MahdiH
el 16 de Ag. de 2020
Respuesta aceptada
Más respuestas (1)
Categorías
Más información sobre Loops and Conditional Statements en Centro de ayuda y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!