Loren谈MATLAB的艺术

将想法转化为MATLAB

请注意

Loren谈MATLAB的艺术已退役,将不再更新。

理解数组预先配置

今天我要介绍的是客座博主Jeremy Greenwald,他在MathWorks的开发组工作。Jeremy从事代码分析器的工作,他将讨论何时预分配MATLAB数组是有用的,何时应该避免它。

内容

为什么预分配是有用的

有许多资源讨论预分配,例如我们的文档以及讨论改进的文章MATLAB分配策略.虽然我们将在这里快速回顾一下预分配的主题,但建议不熟悉这个主题的读者阅读本文提供的一些链接。

假设我们编写以下小函数从某个外部源获取数据。函数返回变量数据给它赋值后,一次一个元素。

函数data = fillDataidx = 1:100 data(idx) = fetchData();结束结束

MATLAB将在执行此循环时多次重新分配内存。重新分配内存后,MATLAB必须将旧值复制到新的内存位置。就计算时间而言,这种内存分配和值的复制可能非常昂贵。它还具有增加峰值内存使用量的效果,因为旧副本和新副本都必须存在一段时间。

在这个例子中,我们知道变量的最终大小数据是1 × 100,所以我们可以通过使用0函数。在这个版本的函数中,只有一个内存分配,数据的值永远不需要从一个位置复制到另一个位置。

函数data = fillDataWithPreallocation data = 0 (1100);idx = 1:100 data(idx) = fetchData();结束结束

虽然对于小数据大小(如1 × 100),这可能不是一个重要的优化,但如果数据大小较大,这可能是一个显著的改进。例如,在图像处理应用程序中,数据可能由数千张高分辨率图像组成,每张图像使用数百兆的内存。对于这样的应用程序,正确使用预分配可以显著提高执行时间。

代码分析器和MATLAB编辑器

MATLAB编辑器使用了一个称为代码分析器检测某些可能不是最优的编程模式。代码分析器提供了关于如何重写这些模式的建议。然后它与编辑器通信,在这些代码下划线。如果将上面的第一个函数复制并粘贴到MATLAB编辑器中,则变量数据以橙色下划线显示。将光标悬停在该变量上,将出现一个工具提示,其中包含以下消息。

变量“data”在每次循环迭代中都会改变大小。考虑预先分配速度。

工具提示还包含一个标有细节.单击该按钮将导致工具提示框展开,并包含消息的更完整解释。最后,在更完整的解释中有一个链接,链接到本文中已经提到的MATLAB文档部分。MATLAB试图提供很多关于何时以及如何预分配的指导。对于上面所示的第一个函数

还有一些其他的代码模式也可以导致变量的大小发生变化,从而使预分配有所帮助。代码分析器可以捕获这些常见模式中的许多。下面的函数包含几个示例。

函数data = fillLotsOfData%所有三个不同的变量都在循环中增长%,这三个都在MATLAB编辑器中下划线data2 = [];data3 = [];idx = 1:100 data1(idx) = fetchData();data2结束(+ 1)= fetchSomeOtherData ();data3 = [data3 fetchYetMoreData()];结束Data = {data1, data2, data3};结束

一个常见的误解

用户经常被告知要预分配变量,我们有时会看到代码中的变量被预分配,即使它是不必要的。这不仅使代码复杂化,而且实际上可能导致预分配本来要减轻的问题,即运行时性能和峰值内存使用。不必要的预分配通常是这样的。

函数data = fillDataWithUnecessaryPreallocation注意代码分析器消息分配给变量'data'的值可能未使用。data = 0 (1100);data = fetchAllData ();结束

的变量数据首先用0函数。然后用返回值重新赋值fetchAllData.第二个作业是造成这种问题的预先分配是要避免的。调用所分配的内存0返回的数据不能重用fetchAllData.相反,一旦调用就会被丢弃fetchAllData成功的回报。的返回值需要两倍的内存,一个块用于预分配的0,另一个块用于的返回值fetchAllData

注意,如果将上述代码复制并粘贴到MATLAB编辑器中,将出现以下代码分析器消息。

赋给变量“data”的值可能未使用。

这表示首先分配给的值(以及底层内存)数据永远不会被使用。在预分配变量的代码行中出现此消息是不需要预分配的好迹象。由于代码分析器可以检测到许多可以从预分配中受益的模式,如果代码分析器没有检测到这样的模式,而检测到一个未使用的变量,那么这些都表明很可能不需要预分配。虽然代码分析器可能偶尔会错过可以从预分配中受益的代码模式,但可以依靠它捕获最常见的这种模式。

结论

预分配不是免费的。因此,默认情况下不应该预分配所有大变量。相反,您应该依靠代码分析器来检测可能从预分配中受益的代码。如果预分配行导致未使用的消息出现,请尝试删除该行,并查看变量更改大小消息是否出现。如果这条消息没有出现,那么最初的一行可能会产生与您所希望的相反的效果。

您看到未使用的变量消息了吗?你被这条信息弄糊涂了吗?代码分析器做了什么才能更清楚地表明存在问题呢?让我们知道在这里




发布与MATLAB®R2012b

|
Baidu
map