MATLAB: How to reduce computation time for nested loops

for loopimage processingMATLABmatricesmatrix array

[N,M] = size(fft_img_test(:,:,1));
B = zeros(N,M,N,M);
for k=1:No_frames
for vy = 1:N
for vx = 1:M
for uy = 1:N
for ux = 1:M
u = uy+vy-2; v = ux+vx-2;
u = mod(u,N); v = mod(v,M);
u = u + 1; v = v + 1;
B(uy,ux,vy,vx) = B(uy,ux,vy,vx) + fft_img_test(uy,ux,k) * fft_img_test(vy,vx,k)...
* conj(fft_img_test(u,v,k));
end
end
end
end
end
phase_B = (angle(B/k));

Best Answer

Your loops sum to over 536.8 million iterations but due to the size of your variables (B has >268.4 million elements) the expansion that would be required to vectorize this would very likely exceed memory capacity.
One thing I changed below to slightly speed up the code is to move the complex conjugate calculations outside of the loop and index the results rather than performing the complex conjugate within the loop.
I've also added a multi-loop waitbar found on the file exchange (here) that will show you the progress of each loop so you don't have to wonder about the progress of the execution.
function [phase_B]=Bispec(fft_img_test, No_frames)
[N,M] = size(fft_img_test(:,:,1));
B = zeros(N,M,N,M);
multiWaitbar('k-loop',0);
multiWaitbar('vy-loop',0);
multiWaitbar('vx-loop',0);
multiWaitbar('uy-loop',0);
multiWaitbar('ux-loop',0);
fft_img_testConj = conj(fft_img_test);
for k=1:No_frames
multiWaitbar( 'k-loop', k/No_frames);
for vy = 1:N
multiWaitbar( 'vy-loop', vy/N);
for vx = 1:M
multiWaitbar( 'vx-loop', vx/M);
for uy = 1:N
multiWaitbar( 'uy-loop', uy/N);
for ux = 1:M
multiWaitbar( 'ux-loop', ux/M);
u = uy+vy-2;
u = mod(u,N);
v = ux+vx-2;
v = mod(v,M);
u = u + 1;
v = v + 1;
B(uy,ux,vy,vx) = B(uy,ux,vy,vx) + fft_img_test(uy,ux,k) * fft_img_test(vy,vx,k) * fft_img_testConj(u,v,k);
% Show current indices
% fprintf('uy,ux,vy,vx,u,v = %d %d %d %d %d %d\n', uy,ux,vy,vx,u,v);
end
end
end
end
end
multiWaitbar('closeall')
phase_B = angle(B/No_frames); % old version: (angle(B/k))
I played around with some vectorization which does speed up the code but since I'm not certain about how the last term using the u and v indices fit in, I stopped here.
fft_img_testConj = conj(fft_img_test);
for k=1:No_frames
multiWaitbar( 'k-loop', k/No_frames);
for vy = 1:N
multiWaitbar( 'vy-loop', vy/N);
for vx = 1:M
multiWaitbar( 'vx-loop', vx/M);
% Vectorization attempt
u = (1:N)+vy-2;
u = mod(u,N);
v = (1:N)+vx-2;
v = mod(v,M);
u = u + 1;
v = v + 1;
B(:,:,vy,vx) = B(:,:,vy,vx) + fft_img_test(:,:,k) .* fft_img_test(vy,vx,k) .* fft_img_testConj(u,v,k);
end
end
end