Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

matlab - Variable appears to change size on every loop iteration - what?

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:

  1. What does that warning mean?
  2. Why is changing variable size every iteration is a bad thing?
  3. 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.

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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 of x will contain the value foo( 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 value foo( 1 ), and so Matlab creates x as a length-1 array. At the second iteration x(2) is assigned the value foo( 2 ) and so Matlab needs to change x 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 of x. If you are lucky, there is enough free space right after x so all that happens is a change to the amount of memory allocated to x 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 the ii-1 elements already in x, allocate this new space for x, copy all ii-1 values already in x to the new spot, and free the old spot x used. This allocate-copy-free operations happening in the background can be extremely time consuming, especially when x is large.

3. How can this problem be solved?

The simplest solution is to pre-allocate all the space x needs before the loop:

x = zeros(1,n); 
for ii=1:n
    x( ii ) = foo( ii );
end

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:

for ii=n:-1:1
    x( ii ) = foo( ii );
end

This way, the first time x is assigned a value it is assigned to its n-th element (the last one) and therefore Matlab immediately allocates room for all n elements of x.
Cool!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...