Search code examples
performancematlabvectorizationprocessing-efficiencybsxfun

Vectorize Triple Loop - MATLAB


I have the following large, very inefficient loop.

P is a [2000 x 200 x 5] matrix
D is a [2000 x 200 x 5] matrix
S is a [200 x 1005] matrix
PS is a [2000 x 1000 x 5] matrix

I want to compute the following loop:

for k=1:2000
   for n=1:200
      for t=1:5
          P(k,n,t) = sum(S(n,t+1:t+1000) .* PS(k,1:1000,t));
      end
   end
end

Obviously this is very inefficient. I tried parfor, but I would rather a vectorized solution. I tried couple of things with bsxfun, but also never managed to get it working.

Thank you.


Solution

  • Here's an almost (almost because we still have a loop, but with only 5 iterations) vectorized approach using powerful matrix-multiplication -

    out = zeros(2000,200,5);
    for t=1:size(P,3) %// size(P,3) = 5
        out(:,:,t) = PS(:,:,t)*S(:,t+1:t+1000).';
    end
    

    Runtime tests and verify output -

    %// Inputs
    D = rand(2000,200,5);
    S = rand(200,1005);
    PS = rand(2000,1000,5);
    
    disp('--------------------- No Matrix-mult-fun')
    tic
    P = zeros(2000,200,5);
    for k=1:2000
       for n=1:200
          for t=1:5
              P(k,n,t) = sum(S(n,t+1:t+1000) .* PS(k,1:1000,t));
          end
       end
    end
    toc
    
    disp('--------------------- Fun fun Matrix-mult-fun')
    tic
    out = zeros(2000,200,5);
    for t=1:size(P,3) %// size(P,3) = 5
        out(:,:,t) = PS(:,:,t)*S(:,t+1:t+1000).';
    end
    toc
    
    error_val = max(abs(P(:)-out(:)))
    

    Output -

    --------------------- No Matrix-mult-fun
    Elapsed time is 70.223008 seconds.
    --------------------- Fun fun Matrix-mult-fun
    Elapsed time is 0.624308 seconds.
    error_val =
         1.08e-12