labview深入探索------類型轉換、數組字符串與內存管理
同其它高級語言一樣,也擁有基本的程序結構,比如,順序結構、條件結構,循環(huán)結構等。也擁有一些自己獨特的程序結構,如隊列、通告、信號、集合等等。
無論是數據類型還是程序結構,都是和內存的使用緊密地結合在一起的,所以深入地了解數據類型和類型之間的轉換以及結構在內存中的存儲形式是非常重要的。
LABVIEW 中涉及到數據類型轉換時,會引起內存復制操作。大的數據類型結構比如數組,字符串和簇在內存中實際占的空間比我們預想的要大,因為LABVIEW同時在內存中也增加了很多必要的信息,正如我們在類型描述符中談到的。使用局部變量和全局變量也要引起內存的復制操作,但是,恰當的編程方式可以避免這個問題。
(一)類型轉換是如何使用內存的
類型轉換會產生兩個問題:增加了類型轉換時間 需要開辟新的BUFFER,增大了內存空間的使用。
有些類型轉換是必要的,但是更多的情況下是我們編程時不注意造成的,對于人為發(fā)生的類型轉換要極力避免。
LV是圖形化編程方式,連線的顏色和線型代表了不同的數據類型,同時在轉換處還會有一個強制轉換點,一般是黑色或者紅色,我們很容易看到在那里發(fā)生了隱含的類型轉換。
上面三個都是要完成+1操作,由于+節(jié)點雖然是多態(tài)的,可以適應各種數據類型,但是默認是DOUBLE型的,由于我先生成了常量1,黃色,導致U32在+節(jié)點處發(fā)生的類型轉換,最后輸出的是DOUBLE類型。而第二個我是先連接的U32,后自動生成的常量1,LABVIEW自動產生的U32常量而不是 DOUBLE,第三個直接調用+1節(jié)點,所以不會發(fā)生類型轉換。所以編程風格是非常重要
上面的圖中,因為SUBVI需要的是DOUBLE類型的數組,而輸入數組是I16的,所以產生了一個強制轉換點,因此,會產生同I16SIZE相同的額外的DOUBLE數組。
對于SIZE非常大的數組,不恰當的類型轉換耗費的內存是驚人的,看下面的圖
上圖第一個框圖,循環(huán)產生10000*64=80K的數組,因為沒有類型轉換,有效地內存重用,數據流上的執(zhí)行數據是80K,前面板數組指示器的操作數據是80K,總計160K
看看上圖中第二個框圖,他用了驚人的400K,不過是乘以一個擴展精度的標量,形成一個擴展精度的數組,然后右重新強制轉換成DOUBLE數組??匆幌率侨绾萎a生的。
---循環(huán)80K
---強制轉換乘法后,數據流上的執(zhí)行數據是160K
---強制轉換成DOUBLE數組,生成另外的80K執(zhí)行數據
---數組指示器 80K操作數據
總計:80K+160K+80K+80K=400K
可以看出中間乘法端子出現的EXT是毫無意義的,不經意間,額外的240K內存被耗費掉了。
所以在數據流中如果數據類型不變,我們將節(jié)省240K的內存,一個重要的原則就是:
盡量始終在數據流中保持同一種數據類型
上圖中,EXAMPEL1和EXAMPLE2是基本相當的,一個是隱含的強制轉換點,一個是用顯式的SGL--》DOUBLE轉換節(jié)點,
它們用的內存是完全相同的,但性能稍微有些差異,隱含轉換速度稍微快了一點,并且節(jié)省的框圖的空間,比較方便。
而EXAMPE 3和EXAMPLE 4則是完全不同的,EXAPLE 3發(fā)生了二次隱含強制轉換,而EXAPLE 4只有一次顯式轉換。節(jié)省了內存和運行時間。
轉換的位置也是很重要的,看看下面的圖
方法一中,兩個數組分別產生8K的數據,其中上面的A的8K經過乘法后得到重用,在轉換C處,產生了4K的執(zhí)行數據(SGL 4BYTE),加上指示器中的操作數據4K,總計24K
方法二中,兩個數組分別產生8K的數據,顯式轉換后,C、D處各產生4K的執(zhí)行數據,乘法后C處的4K得到重用,加上指示器中操作數據4K,總計:8k+8k+4k+4k+4k=28k
方法三中,循環(huán)中對DOUBLE數據顯式轉換成SGL,因此兩個數組各產生4K的數據,其中A處的4K經過乘法節(jié)點后得到重用,加上指示器的4K,總計12K。
對于標量,比如DOUBLE,64位,8個字節(jié),即使發(fā)生了強制類型轉換,可以不必要考慮的它的內存損失。對于字符串和數組,由于它的SIZE是很容易被改變的又沒有SIZE限制,要特別重視。
(二)數組和字符串
LABVIEW中的數組和字符串操作是最影響內存的使用和程序的運行速度。它影響速度的原因在于不斷調用內存管理器來改變數組或者字符串的SIZE,LABVIEW本身也會在必要的時候改變數組和字符串的存儲位置,比如在內存緊張的時候,可能被轉移到虛擬內存。
上面的節(jié)點是需要特別注意的,因為它們都直接改變的數組和字符串的大?。ㄔ貍€數),需要不斷地調用內存管理器,如果是在一個循環(huán)中,會極大地降低程序的性能。
重點看一下BUILD ARRAY函數節(jié)點。
數組所占內存的總量,等于元素個數(size)乘以每個元素所占字節(jié)數。
比如包含10000個數據的DOUBLE類型,DOUBLE 64位,8個字節(jié),占內存總量=10K*8=80K,但這是數組最后所占的字節(jié)數。當你改變數組大小時,由于LV不能重用輸入BUFFER,必須進行額外的內存復制,所以在改變的過程中,會極大消耗內存。所以為了有效地利用內存,盡量不要在循環(huán)中改變數組或者字符串的大小。這樣就可以重用輸入BUFFER 到輸出BUFFER。
建立一個數組有很多種方式,各種方式有很大區(qū)別。
for循環(huán)是固定次數循環(huán),因此在循環(huán)開始之前,就會為索引輸出的數組申請內存空間,一次完成,在循環(huán)內部,不需要改變數組的大小,因此效率是最高的。
第二種方法是效率最差的,每次循環(huán)時都要增加數組的大小,循環(huán)調用內存管理器,是需要極力避免的方法。
第三種方法用的初始化數組節(jié)點,整個數組的的內存空間也是一次申請的,在循環(huán)中替換數組的各個元素,而替換操作是可以重用內存的,這也是一個常用的比較好的方法,但是FOR循環(huán)是LV的基本結構,所以無疑效率是最高的。
評論