变量似乎在每次循环迭代时都会改变大小 - 什么? [英] Variable appears to change size on every loop iteration - what?
问题描述
在编写以下 Matlab 代码时:
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
我收到以下 m-lint 警告:
变量 x
似乎在每次循环迭代时都会改变大小
The variable
x
appears to change size on every loop iteration
我的问题:
- 这个警告是什么意思?
- 为什么每次迭代都改变变量大小是一件坏事?
- 如何解决这个问题?
<小时>
此问题与 此问题 不同,因为它处理的是预分配的更一般方面,而不是它的特定实例.
This question is not duplicate of this one, since it deals with more general aspects of preallocation, rather a specific instance of it.
推荐答案
嗯,第一件事.
这段代码在语法上是正确的,它将正确执行并返回预期的结果:x
的第 ii
元素将包含值 foo(二)
.
然而,在这段小代码运行之前,变量 x
并没有被定义.现在,当循环开始时,x(1)
被赋值为 foo(1)
,因此 Matlab 创建 x
作为长度-1 个数组.在第二次迭代中,x(2)
被赋值为 foo(2)
,因此 Matlab 需要将 x
更改为长度为 2,依此类推:x
在每次迭代时都会改变其长度/大小.
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.
考虑当 x
每次迭代都改变它的大小时,后台会发生什么(在内存分配方面): 在每次迭代中,Matlab 需要找到一个空闲的内存空间来承载 的新大小>x代码>.如果幸运的话,在
x
之后有足够的可用空间,所以所发生的只是更改分配给 x
的内存量并在右侧写入新值现货.
但是,如果在 x
之后没有足够的可用空间,Matlab 必须为 all 中的 ii-1
元素找到一个新位置x
,为 x
分配这个新空间,复制所有 ii-1
值已经在 x
到新位置,并释放旧位置 x
使用.这种在后台发生的无分配复制操作可能非常耗时,尤其是当 x
很大时.
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.
最简单的解决方案是预先分配x
需要在循环之前的所有空间:
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
通过预分配,我们确定 x
已预先分配了它需要的所有内存,因此在循环执行时不需要昂贵的内存分配/复制.
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.
如果你太懒(像我一样)并且不想预先分配,你可以简单地:
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
这样,第一次 x
被分配一个值,它被分配给它的第 n
-th 元素(最后一个),因此 Matlab 立即 为 x
的所有 n
元素分配空间.
酷!
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!
这篇关于变量似乎在每次循环迭代时都会改变大小 - 什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!