罗兰关于MATLAB的艺术

将想法转化为MATLAB

理解数组预先配置

今天我想介绍在MathWorks开发组工作的客座博主Jeremy Greenwald。Jeremy致力于代码分析器,并将讨论什么时候预分配MATLAB数组是有用的,什么时候应该避免。

内容

为什么预分配是有用的

有很多资源都在讨论预分配,比如我们的章节文档以及讨论改进的文章MATLAB分配策略.虽然我们将快速审查此处预付部的主题,但鼓励读者不熟悉此主题,以阅读一些提供的链接。

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

函数data = fillDatadata(idx) = fetchData();结束结束

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

在这个例子中,我们知道变量的最终大小数据是1-by-100,所以我们可以通过预先释放变量来轻松解决问题0函数。在这个版本的函数中,只会有一个内存分配,数据的值永远不必从一个位置复制到另一个位置。

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

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

代码分析器和MATLAB编辑器

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

变量'data'似乎在每次循环迭代时都会改变大小。考虑提前分配。

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

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

函数data = fillLotsOfData所有三个不同的变量都在循环中增长%,并且在MATLAB编辑器中所有三个都加了下划线data2 = [];data3 = [];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.成功返回。这使得需要两倍于需要的内存,预期的零的一个块和一个块的返回值fetchalldata.

请注意,如果将上述代码复制到MATLAB编辑器,则会出现以下代码分析仪消息。

分配给变量“数据”的值可能未使用。

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

结论

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

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




发布与MATLAB®R2012b

|

评论

要留下评论,请点击这里登录到您的MathWorks帐户或创建一个新帐户。