Skip to Main Content Skip to Search
File Exchange
MATLAB Newsgroup
Link Exchange
  Blogs  
 Contest 
MathWorks.com

Loren on the Art of MATLAB

July 12th, 2006

What Are You Really Measuring?

I had an interesting encounter with a colleague, Bob, last week. We were talking about timing some calculations and we realized that the written code was actually measuring something different. Here's a small cautionary tale along with a neat factoid about vectors and for loops in MATLAB.

Contents

The Story

The story Bob and I started off with is less interesting than where we ended up. After looking at some code, I mentioned to Bob that using square brackets when there was no real concatenation was sometimes expensive in MATLAB. You'll see this as a message from mlint. We pared the code in question down to this:

dbtype forsquare
1     %% forsquare
2     for j = 1:ntimes
3         for k=[1:theEnd] 
4             k; 
5         end
6     end

and set out to compare it with this code:

dbtype forparen
1     %% forparen
2     for j = 1:ntimes
3         for k=(1:theEnd) 
4             k; 
5         end
6     end

Notice that the only difference between these M-files is the way format of the expression, the first one using square brackets and the second using parentheses to group the expression. We'll now set out to time the two M-files.

Prep

clc, clear
ntimes = 10;
ntotal = 1e7;
theEnd = ntotal/ntimes;

[], measure with tic-toc

tic, forsquare, toc
Elapsed time is 42.060557 seconds.

(), measure with tic-toc

tic, forparen, toc
Elapsed time is 0.173959 seconds.

[], measure with cputime

t = cputime; forsquare, cputime-t
ans =
   41.2794

(), measure with cputime

t = cputime; forparen, cputime-t
ans =
    0.1702

Explanation

I am timing these on my home laptop with MATLAB R2006a. I have 512 MB of RAM and 1.70 GHz processor. I am performing the timings with both tic toc and cputime tic - toc is easier, but I am not being too careful about what else is running on my machine so I am also using cputime. As you can see, it doesn't make much difference in this case. The construct with the [] is noticeably slower. Why is that?

In forsquare, the for loop expression delimited by the square brackets [] first constructs the full array inside the brackets in preparation for concatenating the array. In this case, there is nothing else being tacked on, so we create the full vector, ntotal elements in length. However, in the case of forparen, the parentheses () are used solely for grouping and MATLAB recognizes the expression as one it can expand during the execution of the for loop. In forsquare we create a large vector and that allocation dominates the time of the operation. In case you don't believe me that expressions in for loops are expanded as they are used, when possible, here's some code to look at:

dbtype forinf
1     %% forinf
2     for j = 1:Inf
3        if j > 17
4            break
5        end
6     end

Notice that the end of the for expression is Inf ! There's no way I have enough memory to create this vector, and yet the code runs just fine:

tic, forinf, toc
Elapsed time is 0.000061 seconds.

Remarks

Timing is a delicate matter. Be sure you know what exactly you are timing when you make comparisons. Do you have any timing war stories to share?


Published with MATLAB® 7.2

8 Responses to “What Are You Really Measuring?”

  1. Loren replied on :

    Sorry for the truncation on the first release of this article.

    –Loren

  2. Steve Amphlett replied on :

    I had often wondered about the use of 1:Inf in a for loop. So now I know. Thanks. Which category does

    for k=1:theEnd

    fit? Is it square or paren?

    - Steve

  3. Loren replied on :

    Steve-

    Regular colon notation in for loops fits into the paren behavior.

    –Loren

  4. Sia replied on :

    Well it’s not exactly a timing issue but I have something to tell about my experience with matlab performance. I brought two of my habits from FORTRAN programming to this amazing Matlab world.

    the first is most of the times it improves the speed dramatically if you use * instead of / if the Denominator is a constant for example instead of a/2 most of the times it helps if you use a*.5 (it makes sense but most of the times we forget to use it)

    And one myth is it is better to write your if statements like this ‘if 1==a’ instead of ‘if a==1′ however I still don’t know if it is just a myth or not

    And probably everyone knows how to use && ;)

  5. Loren replied on :

    Sia-

    I don’t know which version of MATLAB you are using or how you are doing your timing. I used R2006a and ran this script:

    N = 1;
    M = magic(2000);
    K = zeros(size(M));
    t = cputime;
    for num = 1:N,
        K = M*0.5;
    end
    cputime-t
    t = cputime;
    for num = 1:N,
        K = M/2.0;
    end
    cputime-t
    

    and I basically see no difference in scalar multiplication vs. division.

    I similarly tried timing 1==a vs. a==1 and found no difference. I am using a Windows XP laptop.

  6. Sia replied on :

    Loren, It’s not what I meant. you should use / instead of the *. I use R14 (no service pack) on a 2.4 XP laptop 1Gig Ram, please replace your code with this

    clc
    clear all;
    N = 1;
    M = magic(2000);
    K = zeros(size(M));
    t = cputime;
    for num = 1:N,
    K = M*.272423;
    end
    cputime-t
    t = cputime;
    for num = 1:N,
    K = M/3.67076;
    end
    cputime-t

    on mine it shows 30% better performance for * , however it is really dependant on the case you are solving. sometimes I see 300% improvement.

    for the a==1 case I wrote this

    clc;
    clear all;

    t=cputime;

    for i=1:20000000
    for j=i:5
    if 2==j
    alpha=200;
    end
    end
    end
    cputime-t

    clear all;
    t=cputime;
    for i=1:20000000
    for j=i:5
    if j==2
    alpha=200;
    end
    end
    end
    cputime-t

    the difference was just 2 sec in 15 sec, but at least showed that the 1==a case was faster

    have a good week

  7. Loren replied on :

    Sia-

    I fixed my typo in the comment above. I had compared /2 and *.5 in my timings and saw little difference. But I see some difference with your first set of numbers (but much smaller than the 30% you are seeing). Thanks for the interesting test cases.

    There are obvious ways to vectorize some codes like these, but you can’t always do so.

    –Loren

  8. Srini replied on :

    Constructs like if(1==a) above, where the literal is to the left of the “==” help prevent accidents like (if(a=1)). Faster in the sense that it’ll save bug fixing time :)

Leave a Reply


Loren Shure works on design of the MATLAB language at The MathWorks. She writes here about once a week on MATLAB programming and related topics.

  • J.B. Brown: Ah, and I am at fault for simply testing collinearity with the origin in the example above.
  • J.B. Brown: Indeed, > collinear( [0 3],[0 8],[0 -1e21+2e-15] ) ans = 1 > collinear( [0 3],[0 8],[0 -1e22+2e-15]...
  • OkinawaDolphin: Loren, thank you for telling me where to download timeit. Here are the two functions I just tested...
  • Loren: JB- It looks to me like Ilya’s solution and therefore yours are equivalent to the determinant. As Tim...
  • Loren: OkinawaDolphin, timeit can be downloaded from the File Exchange. Steve Eddins is the author. It does not ship...
  • OkinawaDolphin: It seems that neither R2007a nor R2007b have the function timeit, but I investigated computation time...
  • J.B. Brown: It would appear to me that Ilya Rozenfeld’s solution would be the cleanest. Just to help those who...
  • Loren: Markus- Congratulations on winning! And a nice illustration of how the size matters. Small enough, and the...
  • Markus: Hi Loren, which version is fastest also depends very much on the matrix dimensions. Look at my test function:...
  • Duncan: OkinawaDolphin, Regarding why your third example is slower than your second example, the result is in fact...

These postings are the author's and don't necessarily represent the opinions of The MathWorks.

Related Topics