its ask to prelocate speed on p line. why?

1 view (last 30 days)
% code to perform complete response
tic
t1=0:0.1:10; %time
for i=1:length(t1)
t=t1(:,i);
p(i,:)=(1000.*dirac(t))/11 - (15000000.*exp(-(7500.*t)/11).*(cos((1191998652453536545^(1/2).*t)/1441792) + (45126202170707309.*1191998652453536545^(1/2).*sin((1191998652453536545^(1/2).*t)/1441792))/468712942123169826078720000))/121;
end
toc

Accepted Answer

Walter Roberson
Walter Roberson on 13 Jan 2022
Why?
In most circumstances, MATLAB does not examine the context to figure out how many iterations of a loop will be done, and so MATLAB does not automatically pre-create variables as being as large as would be needed.
Consider for example,
for i = 1 : 10
p(i) = i/f(i);
end
You might think that MATLAB should be smart enough to pre-allocate p to be 10 elements long.
However...
  1. Suppose that you use the debugger and stop after (say) the 4th iteration. Then only 4 values have been assigned into p, at that point, and it would be a mistake for p to be showing length 10
  2. Suppose f(i) raises an error() at some point, then p should only reflect the number of elements assigned to it before the error() was raised
So in most cases it would break MATLAB's computational model that at any point, variables only reflect what has been directly computed or assigned to them, rather than what the variables might become later.
So, MATLAB cannot pre-assign to the expected final size of p -- not and still respect the computational model that MATLAB uses.
What difference does it make that you do not pre-allocate? Why does MATLAB bother to warn you?
Well, with p not existing before the loop, the first iteration of your code assigns a scalar to p. Then in the second iteration, the p(:,2) needs to assign a scalar into p(2), but p is only length 1 at that point. MATLAB [mostly] does not expand p "in place" because most of the time there is no unallocated memory sitting immediately beside the existing memory that can be just moved into. Instead, MATLAB has to allocate a new block of memory that is one more column wide, and copy the old values into there, and then copy in the new value, and then release the old block of memory. Then on iteration 3, again MATLAB has to create a new block, copy the two existing values in, copy in the new value, and release the old block of memory. On iteration 4, new block, copy in the 3 existing values, etc.. 10th iteration, new block, copy in the 9 existing values, and so on. For iteration #i, the (i-1) existing values have to be copied in, and so on. Your t1 is 101 elements long, so on iteration 101 it has to create a new block, copy in the 100 existing values, copy in the new value, release the block of 100... and then it can end the loop.
Let us count: Iteration 1, it copied 1 value. Iteration 2 it copied 1 value. Iteration 3 it copied 2 values. Iteration 4 it copied 3 values... iteration 101 it copied 100 values. Total number of values copied: 0 + 1 + 2 + 3 + ... 100 . Which is 100*101/2 = 5050 values copied in total. Which adds up and gets slower and slower the more iterations you use.
Whereas if you had pre-allocated p as 101 long, then it would only be copying in the single new value each time and you would have linear performance.
So it warns you because you have an easily-removable inefficiency.
  3 Comments
Walter Roberson
Walter Roberson on 14 Jan 2022
An argument could be made (I have seen it made) that the presence of break/continue/return signals conditional dynamics that might have to be implemented with reduced efficiency to match the computation model, but that (the argument goes) for loops with unconditional expansion by a prior-computable size per loop should invoke automatic preallocation, since you "know" that the loop will be run that many times. Except you don't know that, as I describe.
Walter Roberson
Walter Roberson on 14 Jan 2022
In cases where you could reasonably predict a maximum number of iterations, a plausible implementation would be to preallocate (and internally record) the maximum size, but also keep track of the maximum dimension that has been written to.
If you have preallocated a chunk of memory, you can expand into the chunk without issue if you are using a vector, or if all lower dimensions than you are expanding into are kept the same size. If, for example, you have a 2d array that has growing number of rows, then the model is that the memory that has been written into is contiguous.
You could imagine that if enough memory were preallocated but margins exist for each dimension saying how far you have grown so far, that the internal routines could take that into account. But you need to repackage into contiguous memory if you are calling into MKL or BLAS... or if you are calling into an external function like a mex that might not know about the new organization....

Sign in to comment.

More Answers (0)

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Products


Release

R2021b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!