labview深入探索------类型转换、数组字符串与内存管理

2015-08-21 11:15:02   来源:eefocus   

关键字: labview  类型转换  数组字符串  内存管理

labview同其它任何高级语言一样,都支持多种基本数据类型和复合数据类型,基本数据类型包括U8、U16、U32、I8、I16、I32,SGL,DBL,EXT等等,复合数据类型包括数组、簇、字符串、路径等。


同其它高级语言一样,也拥有基本的程序结构,比如,顺序结构、条件结构,循环结构等。也拥有一些自己独特的程序结构,如队列、通告、信号、集合等等。

无论是数据类型还是程序结构,都是和内存的使用紧密地结合在一起的,所以深入地了解数据类型和类型之间的转换以及结构在内存中的存储形式是非常重要的。

LABVIEW 中涉及到数据类型转换时,会引起内存复制操作。大的数据类型结构比如数组,字符串和簇在内存中实际占的空间比我们预想的要大,因为LABVIEW同时在内存中也增加了很多必要的信息,正如我们在类型描述符中谈到的。使用局部变量和全局变量也要引起内存的复制操作,但是,恰当的编程方式可以避免这个问题。

(一)类型转换是如何使用内存的

类型转换会产生两个问题:增加了类型转换时间 需要开辟新的BUFFER,增大了内存空间的使用。

有些类型转换是必要的,但是更多的情况下是我们编程时不注意造成的,对于人为发生的类型转换要极力避免。

LV是图形化编程方式,连线的颜色和线型代表了不同的数据类型,同时在转换处还会有一个强制转换点,一般是黑色或者红色,我们很容易看到在那里发生了隐含的类型转换。
 


上面三个都是要完成+1操作,由于+节点虽然是多态的,可以适应各种数据类型,但是默认是DOUBLE型的,由于我先生成了常量1,黄色,导致U32在+节点处发生的类型转换,最后输出的是DOUBLE类型。而第二个我是先连接的U32,后自动生成的常量1,LABVIEW自动产生的U32常量而不是 DOUBLE,第三个直接调用+1节点,所以不会发生类型转换。所以编程风格是非常重要


上面的图中,因为SUBVI需要的是DOUBLE类型的数组,而输入数组是I16的,所以产生了一个强制转换点,因此,会产生同I16SIZE相同的额外的DOUBLE数组。
对于SIZE非常大的数组,不恰当的类型转换耗费的内存是惊人的,看下面的图


上图第一个框图,循环产生10000*64=80K的数组,因为没有类型转换,有效地内存重用,数据流上的执行数据是80K,前面板数组指示器的操作数据是80K,总计160K

看看上图中第二个框图,他用了惊人的400K,不过是乘以一个扩展精度的标量,形成一个扩展精度的数组,然后右重新强制转换成DOUBLE数组。看一下是如何产生的。

---循环80K
---强制转换乘法后,数据流上的执行数据是160K
---强制转换成DOUBLE数组,生成另外的80K执行数据
---数组指示器 80K操作数据
总计:80K+160K+80K+80K=400K

可以看出中间乘法端子出现的EXT是毫无意义的,不经意间,额外的240K内存被耗费掉了。

所以在数据流中如果数据类型不变,我们将节省240K的内存,一个重要的原则就是:

尽量始终在数据流中保持同一种数据类型




上图中,EXAMPEL1和EXAMPLE2是基本相当的,一个是隐含的强制转换点,一个是用显式的SGL--》DOUBLE转换节点,
它们用的内存是完全相同的,但性能稍微有些差异,隐含转换速度稍微快了一点,并且节省的框图的空间,比较方便。

而EXAMPE 3和EXAMPLE 4则是完全不同的,EXAPLE 3发生了二次隐含强制转换,而EXAPLE 4只有一次显式转换。节省了内存和运行时间。

转换的位置也是很重要的,看看下面的图



方法一中,两个数组分别产生8K的数据,其中上面的A的8K经过乘法后得到重用,在转换C处,产生了4K的执行数据(SGL 4BYTE),加上指示器中的操作数据4K,总计24K

方法二中,两个数组分别产生8K的数据,显式转换后,C、D处各产生4K的执行数据,乘法后C处的4K得到重用,加上指示器中操作数据4K,总计:8k+8k+4k+4k+4k=28k

方法三中,循环中对DOUBLE数据显式转换成SGL,因此两个数组各产生4K的数据,其中A处的4K经过乘法节点后得到重用,加上指示器的4K,总计12K。

对于标量,比如DOUBLE,64位,8个字节,即使发生了强制类型转换,可以不必要考虑的它的内存损失。对于字符串和数组,由于它的SIZE是很容易被改变的又没有SIZE限制,要特别重视。


(二)数组和字符串

LABVIEW中的数组和字符串操作是最影响内存的使用和程序的运行速度。它影响速度的原因在于不断调用内存管理器来改变数组或者字符串的SIZE,LABVIEW本身也会在必要的时候改变数组和字符串的存储位置,比如在内存紧张的时候,可能被转移到虚拟内存。



上面的节点是需要特别注意的,因为它们都直接改变的数组和字符串的大小(元素个数),需要不断地调用内存管理器,如果是在一个循环中,会极大地降低程序的性能。

重点看一下BUILD ARRAY函数节点。

数组所占内存的总量,等于元素个数(size)乘以每个元素所占字节数。
比如包含10000个数据的DOUBLE类型,DOUBLE 64位,8个字节,占内存总量=10K*8=80K,但这是数组最后所占的字节数。当你改变数组大小时,由于LV不能重用输入BUFFER,必须进行额外的内存复制,所以在改变的过程中,会极大消耗内存。所以为了有效地利用内存,尽量不要在循环中改变数组或者字符串的大小。这样就可以重用输入BUFFER 到输出BUFFER。

建立一个数组有很多种方式,各种方式有很大区别。


for循环是固定次数循环,因此在循环开始之前,就会为索引输出的数组申请内存空间,一次完成,在循环内部,不需要改变数组的大小,因此效率是最高的。

第二种方法是效率最差的,每次循环时都要增加数组的大小,循环调用内存管理器,是需要极力避免的方法。

第三种方法用的初始化数组节点,整个数组的的内存空间也是一次申请的,在循环中替换数组的各个元素,而替换操作是可以重用内存的,这也是一个常用的比较好的方法,但是FOR循环是LV的基本结构,所以无疑效率是最高的。

[1] [2]
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。
编辑:什么鱼
本文引用地址: http://www.eeworld.com.cn/Test_and_measurement/2015/0821/article_12876.html
[发表评论]
[加入收藏]
[打印本页]
[关闭窗口]
[返回顶部]
[RSS订阅]
小广播
每日新闻
最热点击
本周热门资源推荐
EEWORLD独家
论坛精华
精选博文