The traditional mantra of Matlab is that matrix operations are fast and loops are slow. There are many resources available online that provide standard tricks to avoid loops. A quick search on “Matlab vectorization” provides an endless list of tutorials and useful code snippets.
However, this mantra is false for recent versions of Matlab (6.5+). It is possible to write loops that match (and occasionally exceed) the performance of vectorized code. Blocks of code that adhere to acceleration guidelines are accelerated. Each time Matlab encounters a line that does not adhere to the guidelines, it must evaluate the code separately (i.e. slowly!).
Guidelines for Acceleration
- Data types. Only use or modify logical, char, int8, uint8, int16, uint16, int32, uint32, and double variables. Do not use function handles, cell arrays, sparse arrays, classes, java objects, or single precision numbers.
- Type consistency. Do not change the data type of any variables. For example, do not assign a character to X and then later assign a double to X.
- Array dimensions. Use a maximum of three dimensions in all arrays (the arrays can be very large).
- Loop range. Use a range of scalar values. In particular, do not use the column-vector index feature (e.g. for index = eye(10) ).
- Separate lines. Do not use more than one command (delineated by a semicolon) per line. This is not strictly necessary in many cases, but it does affect performance if one command adheres to the guidelines and one does not.
- Imaginary numbers. Use the imaginary number notation when possible. For example, write 3+4i instead of 3 + 4*i, and write 2 + 1i instead of 2 + i (otherwise, Matlab needs to parse the line separately to determine whether “i” is a variable being added).
- Functions. Use only built-in functions and operations. Do not use any functions that overload built-in functions.
Of these guidelines, the last one needs the most explanation. Operations like “+” and “*” are accelerated. To check whether a function is built-in, use the command “which.” For example, type “which sin” to see that the sin function is built-in. On the other hand, type “which repmat” to see that repmat is actually an *.m file, so loops containing “repmat” will not be accelerated. You may be surprised by how many basic operations (like repmat) are in fact Matlab functions. Note that “built-in” refers to the fact that the function is not an *.m file, not that the function is bundled with a default Matlab installation.
A brief digression on repmat
I was very surprised when I first learned that repmat was not an intrinsic function. There is a quick workaround for most cases. Recall that there are two types of indexing arrays: logical and numerical. A logical indexing array will retrieve the elements corresponding to true, whereas a numerical indexing array will retrieve the elements corresponding to indices. Thus:
A = 6;
B = A( ones(m, n) ); % get the element A(1), then get the element A(1), etc.
does the same thing as repmat(6, m, n). Note that “ones” is a built-in function! Similar tricks will allow you to repmat more general matrices.
The age-old sayings about premature optimization still hold, despite how much easier it may be to optimize with the loop acceleration feature. The above discussion on repmat hopefully shows that if you are serious about acceleration, you will need to reinvent the wheel many times. In some cases, using functions like repmat and kron within loops is worth the small performance penalty.
Moreover, it may be much faster to write a string of vectorized commands rather than one long but self-contained and efficient for loop. In this case, it is difficult to predict which method will execute faster, but it will almost certainly be faster to code the vectorized commands.
As always, use tools like the profiler to find out where it is truly worthwhile to optimize your code. Remember that Matlab is ultimately about rapid development with acceptable performance. Don’t focus on performance to the extent that you lose more time on development than you gain in runtime!
- Andrew Chalk on Evidence for Strong EMH
- vlad on Jensen’s Alpha
- Anon on Dealing with occasionally non-numeric data in Matlab
- Quant on Jensen’s Alpha
- Anonymous on Jensen’s Alpha