When writing the following Matlab code:
for ii=1:n
x(ii) = foo( ii ); % foo is some function of ii that cannot be vectorized.
end
I get the following m-lint warning:
The variable
x
appears to change size on every loop iteration
My question:
- What does that warning mean?
- Why is changing variable size every iteration is a bad thing?
- How can this problem be solved?
This question is not duplicate of this one, since it deals with more general aspects of preallocation, rather a specific instance of it.
This answer is simplified sparing some of the details.
M-lint warns the programmer when it spots an opportunity to pre-allocate memory. Pre-allocating memory improves processing time as it simplifies tasks outside of a MATLAB programmer's direct control related to memory hardware management.
A changing variable size is not always bad; however, it is good programming practice to code for faster processing speed. Faster processing speed is more noticeable when the code uses many iterations or much more memory.
Other MATLAB pre-allocation methods recommended will work; however, the following methods may be more intuitive.
Assigning a value to a pre-allocated array.
Notes:
Assigning a value to a pre-allocated multi-dimensional array:
A lazy way to pre-allocate is to assign a zero to only the last element in an array.
There is a lot of material out there on the subject. Here are a few selected links for more information:
Official documentation and technical solutions:
MathWorks Blogs:
Community Blogs:
Related Stack Overflow questions/answers:
Well, first thing first.
1. What does this warning mean?
This code is correct in terms of syntax and it will execute correctly returning the expected result: the
ii
-th element ofx
will contain the valuefoo( ii )
.However, before this small piece of code runs, the variable
x
is not defined. Now, when the loop starts,x(1)
is assigned the valuefoo( 1 )
, and so Matlab createsx
as a length-1 array. At the second iterationx(2)
is assigned the valuefoo( 2 )
and so Matlab needs to changex
to be of length 2, and so on:x
changes its length/size at each iteration.2. Why is changing variable size every iteration is a bad thing?
Consider what happens in the background (in terms of memory allocation) when
x
changes its size every iteration: At each iteration Matlab needs to find a free memory space to host the new size ofx
. If you are lucky, there is enough free space right afterx
so all that happens is a change to the amount of memory allocated tox
and writing the new value at the right spot.However, if there is not enough free space just after
x
, Matlab has to find a new spot for all theii-1
elements already inx
, allocate this new space forx
, copy allii-1
values already inx
to the new spot, and free the old spotx
used. This allocate-copy-free operations happening in the background can be extremely time consuming, especially whenx
is large.3. How can this problem be solved?
The simplest solution is to pre-allocate all the space
x
needs before the loop:By pre-allocating we ascertain that
x
is allocated all the memory it requires up-front, thus no costly memory allocation/copy is needed when the loop is executing.An alternative cool solution to the problem
If you are too lazy (like me) and don't want to pre-allocate you can simply:
This way, the first time
x
is assigned a value it is assigned to itsn
-th element (the last one) and therefore Matlab immediately allocates room for alln
elements ofx
.Cool!
My answer is a bit late, but there are a few things I'd mention regarding array growth and pre-allocation in MATLAB.
The first thing to note is that MATLAB has improved automatic array growth performance a lot in recent versions, so the performance hit implied by the warning might not be too bad if you do it right (see below). Still, best practice is to pre-allocate your array (e.g. with
zeros
).The Warning Explained
As of R2014a, the detailed explanation for the warning states the following:
From this excerpt, it should be fairly clear why pre-allocation is a smart idea if you are at all concerned with performance.
Side note: There is limited information about the algorithm used for reallocation during array growth, but some information was provided on the same blog post by Steve Eddins, which I summarized in this previous answer.
Automatic Array Growth Optimization
If you want to use dynamic array resizing by growing along a dimension (without-preallocation), there are ways to do it right. See this this MathWorks blog post by Steve Eddins. The most important thing to note is that you should grow along the last dimension for best performance. This is not an issue in your case since the array is 1D. So, if you decide to let it ride, put
%#ok<SAGROW>
on the same line as the warning, after the culprit code, to silence the warning.Yair discusses dynamic array resizing in another post on his blog. Also, there are ways of allocating an array without initializing using some hairy MEX API acrobatics, but that's it.
Pre-allocation
Pre-allocation is recommended. Get in the habit, learn to love
zeros
. If you are determined to squeeze every bit of performance out of MATLAB, Yair Altman has a couple of excellent articles on the topic of memory pre-allocation: