初始化或预分配的最佳实践 - MATLAB

3
我的问题并不仅仅依赖于一段代码,而是更加概念性的。
与某些编程语言不同,MATLAB不需要在使用变量之前明确初始化。例如,下面这个例子是在脚本文件中定义'myVector'的完全合法的:
myVector = vectorA .* vectorB

我的问题是:初始化变量(如上面的“myVector”)并赋值,还是在程序中保持初始化更快?

这是我要讨论的直接比较:

在整个程序中进行初始化:

varA = 8;
varB = 2;

varC = varA - varB;
varD = varC * varB;

启动时进行初始化:

varA = 8;
varB = 2;
varC = 0;
varD = 0;

varC = varA - varB;
varD = varC * varB;

一方面,似乎没有理由为这些额外的代码行浪费空间。另一方面,将程序的所有内存一次性分配而不是在运行时期间分散分配可能更快。有人能提供一些见解吗?
2个回答

5

将您的初始化代码复制并粘贴到MATLAB编辑器窗口中,您会收到以下警告:

enter image description here

如果进入详细信息,您会看到以下内容:

Explanation 
The code does not appear to use the assignment to the indicated variable. This situation occurs when any of the following are true:
Another assignment overwrites the value of the variable before an operation uses it.
The specified argument value contains a typographical error, causing it to appear unused.
The code does not use all values returned by a function call...

在我们的情况下,此警告的原因是 代码没有使用所有值。这表明初始化/预分配对于该情况没有帮助。

何时应进行预分配?

根据我的经验,在后面需要索引其中一部分时,预分配有所帮助。

因此,如果您需要索引varC的一部分来存储结果,则预分配会有所帮助。因此,以下做法更有意义-

varC = zeros(...)
varD = zeros(...)
varC(k,:) = varA - varB;
varD(k,:) = varC * varB;

如果在索引时超出了varC的大小,MATLAB会花费时间尝试为其分配更多的内存空间,这会稍微减慢速度。因此,请预先分配输出变量的 最大大小,以便用于存储结果。但是,如果您不知道结果的大小,则必须将结果附加到输出变量中,这肯定会减慢速度。


我注意到,如果你不停地延长一个向量(例如在循环中),MATLAB会发出初始化的警告。实际上,这就是促使我提问的原因。为了澄清:当变量的大小正在改变时,应该初始化为最大大小,这样MATLAB就不必继续分配更多的内存;而当大小不变时,只需要在需要时定义变量即可。 - h3half
1
@h3half 我认为这就是“索引”的作用,第二部分对此进行了讨论或触及到了。 - Divakar
1
@h3half 我一定是写成了“最大尺寸”,刚刚修改了。 - Divakar

3

好的!我已经做了一些测试,这是结果。

这是我用于“throughout”变量赋值的代码:

tic;
a = 1;
b = 2;
c = 3;
d = 4;
e = a - b;
f = e + c;
g = f - a;
h = g * c;
i = h - g;
j = 9 * i;
k = [j i h];
l = any(k);
b2(numel(b2) + 1) = toc

这里是“At Start”变量分配的代码:
```

这里是“At Start”变量分配的代码:

```
tic;
a = 1;
b = 2;
c = 3;
d = 4;
e = 0;
f = 0;
g = 0;
h = 0;
i = 0;
j = 0;
k = 0;
l = 0;
e = a - b;
f = e + c;
g = f - a;
h = g * c;
i = h - g;
j = 9 * i;
k = [j i h];
l = any(k);
b1(numel(b1) + 1) = toc

我将'b1'和'b2'的时间记录下来。每次记录时,只有MATLAB和Chrome是打开的,而且MATLAB中也只有这个脚本文件在运行。总共进行了201次记录。由于程序第一次运行时需要编译,因此我忽略了两者的第一个时间值(我不关心编译时间)。
为了求平均值,我使用了:
mean(b1(2:201))

并且

mean(b2(2:201))

结果如下:

"Throughout": 1.634311562062418e-05 秒 (0.000016343)

"At Start": 2.832598989758290e-05 秒 (0.000028326)

有趣的是(或许也不是,谁知道呢),只在需要时定义变量,分散在程序中的速度几乎是两倍。

我不知道这是因为MATLAB分配内存的方式(也许它只抓取巨大的块并且不需要每次定义变量时都分配更多内存?)还是分配速度非常快,使得额外的代码行数被弱化了。

注意:正如Divakar指出的那样,在使用数组时可能会有所不同。然而,当变量大小不改变时,我的测试结果应该成立。

简而言之,将变量设置为零以后再改变它是很慢的


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接