arraysmatlabmemory-managementpre-allocation

Preallocating arrays in Matlab?


I am using a simple for loop to crop a large amount of images and then storing them in a cell array. I keep getting the message:

The variable croppedSag appears to change size on every loop iteration. Consider preallocating for speed.

I have seen this several times before while coding in MATLAB. I have always ignored it and am curious how much preallocating will increase the runtime if I have, say, 10,000 images or a larger number?

Also, I have read about preallocating in the documentation and it says to use zeros() for that purpose. How would I use that for the code below?

croppedSag = {};
for i = 1:sagNum
    croppedSag{end+1} = imcrop(SagArray{i},rect);
end

I didn't quite follow the examples in the documentation.


Solution

  • Pre-allocating an array is always a good idea in Matlab. The alternative is to have an array which grows during each iteration through a loop. Each time an element is added to the end of the array, Matlab must produce a totally new array, copy the contents of the old array into the new one, and then, finally, add the new element at the end. Pre-allocating eliminates the need to allocate a new array and spend time copying the existing contents of the array into the new memory.

    However, in your case, you might not see as much benefit as you might expect. When copying the cell array to a new, enlarged cell array, Matlab doesn't actually have to copy the contents of the cell array (the image data), but only pointers to that data.

    Nonetheless, there is no reason not to pre-allocate (unless you actually don't know the final size in advance). Here's a pre-allocated version of your loop:

    croppedSag = cell(1, sagNum);
    for ii = 1:sagNum
        croppedSag{ii} = imcrop(SagArray{ii}, rect);
    end
    

    I also changed the index variable "i" to "ii" so that it doesn't over-write the imaginary unit.

    You can also re-write this loop in one line using the cellfun function:

    croppedSag = cellfun(@(im) imcrop(im, rect), SagArray);
    

    Here's a blog entry that might be informative: