labview 内存的优化
一. VI 在内存中的结构
打开一个VI的属性面板(VI Proper
ties),其中的“内存使用”(Memory Usage)是用来查看这个VI内存占用情况的。它显示了一个VI内存占用所包含的四个主要部分:前面板、框图、代码和数据,以及这四个部分的总和。但在打开一个VI时,这四段内容并不是同时都会被LabVIEW调入内存的。
当我们打开一个主VI时,主VI连同它的所有子VI的代码和数据段都会被调入内存。由于主VI的前面板一般情况下是打开的,它的前面板也就同时被调入内存。但是此时主VI的框图和子VI的前面板、框图并没有被调入内存。只有当主动查看主VI的框图或是打开子VI的前面板和框图时,它们才会被调入。
基于LabVIEW的这种内存管理的特性,我们在编写VI的时候可以通过以下方法来优化LabVIEW程序的内存使用。
第一,把一个复杂VI分解为数个子VI。子VI的使用会增添额外的前面板和框图的空间,但并不增添额外的代码和数据空间。由于程序运行时只有代码和数据被调入内存,因此使用子VI不会占用额外的内存。使用子VI的好处还在于当子VI运行结束时,LabVIEW可以及时收回子VI的数据空间,从而改善了内存的使用效率。
第二,在没有必要时不要设置子VI的重入(Reentrant)属性。重入型VI每次运行时都会对自己使用的数据生成一个副本,这增加了内存开销。
第三,主VI的面板通常就是用户界面,需要显示给用户。但是要尽量避免开启子VI前面板。比如,在子VI中使用与其前面板控件有关的属性节点(Property Node)会导致它的前面板被调入内存中,增加了内存开销,所以要尽量避免在子VI中使用主面板控件的属性节点来设置控件的值,而可以用局部变量等方法来替代。
第四,我们可以放心地在 VI 的前面板(对于非界面VI)和框图里添加图片,注释等信息来帮助你编写、维护LabVIEW程序,这些帮助信息不会在VI运行时占用内存。
二. 内存泄漏。
LabVIEW与C语言不同,它没有任何分配或释放内存的语句,LabVIEW可以自动管理内存,在适当的时候分配或收回内存资源[1]。这样就避免了C语言中常见的因为内存管理语句使用不当而引起的内存泄漏。
在LabVIEW中一般只有一种情况能够引起内存泄漏,即你打开了某些资源,却忘记了关闭它们。比如,在对文件操作时,我们需要先打开这个文件,返回它的句柄。随后如果忘记了关闭这个句柄,它所占用的内存就始终不会被释放,从而产生内存泄漏。LabVIEW中其它带有打开句柄的函数或VI也会引起同样的问题。
由于内存泄漏是动态产生的,我们无法通过VI的属性面板来查看,但可以通过Windows自带的任务管理工具来查看LabVIEW程序内存是否有泄漏。也可以使用LabVIEW的Profile (Tools>>Advanced>>Profile VIs)工具来查看某个VI运行时内存的分配情况。
三. 缓存重用
LabVIEW程序主要是数据流驱动型的。数据传递到不同节点时往往需要复制一个副本。这是LabVIEW为了防止数据被节点改变引起错误所做的一种数据保护措施。只有当目标节点为只读节点,不可能对输入数据作任何更改时,才不在这些节点处做备份。例如,数组索引节点(Index)是不会改变数组值的,LabVIEW在这里就不为输入数组做备份。对于加减法运算等肯定改变输入数据的节点,LabVIEW往往需要对输入或输出数据作备份。有些LabVIEW程序,比如涉及到大数组运算的程序,内存消耗极大。其主要原因就是LabVIEW在运算时为数组数据生成了过多的副本。
实际上很多LabVIEW节点是允许使用缓存重用的,这类似C语言调用子函数所使用的地址传递。通过合理设计和使用缓存重用节点,可以大大优化LabVIEW程序的内存使用。使用LabVIEW 7.1的Tool>>Advanced>>Show Buffer Allocations工具可以在VI框图中查看缓存的分配情况。打开该工具,凡是在框图中有缓存分配的地方,都会显示出一个黑点。
下面是几个最常用节点的试验结果。LabVIEW节点众多,不可能一一列举,文中未提及的节点读者在编程时自己可以尝试。
1. 一般顺序执行VI中的运算节点
3