洛伦谈MATLAB的艺术

将想法转化为MATLAB

理解数组预分配

今天,我想向大家介绍在MathWorks开发组工作的特邀博主Jeremy Greenwald。Jeremy从事代码分析器的工作,将讨论预分配MATLAB数组何时有用以及何时应该避免。

目录

为什么预分配是有用的

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

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

函数数据=填充数据对于data(idx) = fetchData();终止终止

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

在这个例子中,我们知道变量的最终大小数据是1乘100,所以我们可以很容易地解决这个问题,通过用作用在这个版本的函数中,只有一个内存分配,数据值不必从一个位置复制到另一个位置。

函数data = fillDataWithPreallocation data = 0 (1100);对于data(idx) = fetchData();终止终止

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

代码分析器和MATLAB编辑器

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

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

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

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

函数data = fillLotsOfData%所有三个不同的变量都在循环中增长%在MATLAB编辑器中,所有三个都加了下划线data2 = [];data3 = [];对于idx=1:100数据1(idx)=获取数据();data2(end+1)=fetchSomeOtherData();data3=[data3 fetchYetMoreData()];终止Data = {data1, data2, data3};终止

一个常见的误解

用户经常被告知要预分配变量,因此我们有时会看到一些代码在不必要的情况下也会预分配变量。这不仅使代码变得复杂,而且实际上还会导致预分配旨在缓解的问题,例如,运行时性能和峰值内存使用。不必要的预分配通常是这样的。

函数data = fillDataWithUnecessaryPreallocation%注意代码分析器消息%分配给变量“data”的值可能未使用。数据=零(1100);data=fetchAllData();终止

的变量数据是首先用作用然后用返回值重新分配它fetchAllData. 第二项任务是造成了预先分配要避免的问题。调用分配给的内存无法对从返回的数据重复使用fetchAllData.相反,一旦调用,它就被丢弃fetchAllData成功的回报。这样做的结果是需要两倍于实际需要的内存,一块用于预分配的零,一块用于返回值fetchAllData

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

赋给变量'data'的值可能未被使用。

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

结论

预分配不是免费的。因此,默认情况下不应预分配所有大变量。相反,您应该依赖代码分析器来检测可能受益于预分配的代码。如果预分配行导致未使用的消息出现,请尝试删除该行,并查看是否出现可变大小消息。如果此消息未出现,则原始行可能具有与您所希望的相反的效果。

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




与MATLAB®R2012b一起发布

|

评论

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