Search code examples
matlabsumprocessing-efficiencymemory-efficientspace-efficiency

Fastest way to sum the elements of a matrix


I have some problems with the efficiency of my code. Basically my code works like this:

a = zeros(1,50000);
for n = 1:50000
    a(n) = 10.*n - 5;
end
sum(a);

What is the fastest way to solve the sum of all the elements of this matrix?


Solution

  • first you want to remove your for loop by making it a vector multiplication:

    tic
    a = zeros(1,50000);
    b = [1:50000];
       a = 10.*b-5;
    result = sum(a);
    toc
    Elapsed time is 0.008504 seconds.
    

    An alternative way is to simplify your operation, you are multiplying 1 to 50000 by 10 and subtracting 5 then taking the sum (which is a single number), which is equivalent to:

    tic
    result = sum(1:50000)*10 - 5*50000;
    toc
    Elapsed time is 0.003851 seconds.
    

    or if you are really into Math (this is a pure mathematical expression approach) :

    tic
    result = (1+50000)*(50000/2)*10 - 5*50000;
    toc
    Elapsed time is 0.003702 seconds.
    

    and as you can see, a little math can do greater good than pure efficient programming, and actually, loop is not always slow, in your case, the loop is actually faster than the vectorized method:

    tic
    a = zeros(1,50000);
      for n = 1:50000
         a(n)=10.*n-5;
      end
    sum(a);
    toc
    Elapsed time is 0.006431 seconds.
    

    Timing

    Let's do some timing and see the results. The function to run it yourself is provided at the bottom. The approximate execution time execTime is in seconds and the percentage of improvement impPercentage in %.

    Results

    • R2016a on OSX 10.11.4

                     execTime     impPercentage
                    __________    _____________
      loop          0.00059336         0       
      vectorized    0.00014494    75.574       
      adiel         0.00010468    82.359       
      math          9.3659e-08    99.984       
      

    Code

    The following function can be used to generate the output. Note that it requires minimum R2013b to be able to use the built-in timeit-function and table.

    function timings
    %feature('accel','on')      %// commented out because it's undocumented
    cycleCount = 100;
    execTime = zeros(4,cycleCount);
    names = {'loop';'vectorized';'adiel';'math'};
    w = warning;
    warning('off','MATLAB:timeit:HighOverhead');
    for k = 1:cycleCount
        execTime(1,k) = timeit(@()loop,1);
        execTime(2,k) = timeit(@()vectorized,1);
        execTime(3,k) = timeit(@()adiel,1);
        execTime(4,k) = timeit(@()math,1);
    end
    warning(w);
    execTime = min(execTime,[],2);
    impPercentage = (1 - execTime/max(execTime)) * 100;
    table(execTime,impPercentage,'RowNames',names)
    
    
    function result = loop
    a = zeros(1,50000);
    for n = 1:50000
        a(n) = 10.*n - 5;
    end
    result = sum(a);
    
    function result = vectorized
    b = 1:50000;
    a = 10.*b - 5;
    result = sum(a);
    
    function result = adiel
    result = sum(1:50000)*10 - 5*50000;
    
    function result = math
    result = (1+50000)*(50000/2)*10 - 5*50000;