鄧澤平,崔建峰,梁志劍,劉慧豐
(1.中北大學 電子測試技術重點實驗室,山西 太原 030051;2.北京特種車輛試驗場,北京 100072)
隨著現代工業和信息技術的快速發展,各測試領域的測試精度和采樣頻率都得到提高[1],被測設備的智能化程度越來越高、 系統結構也更加復雜.與此同時,在測試中產生的數據量也隨之驟增,在某型號裝甲車輛的振動測試中,采樣頻率為3 000 Hz,每個數據點占用2個字節,經過一個小時采集數據量就達到20 MB以上(僅是車輛測試中一個通道的數據量).由此可見,大容量測試數據的處理成為不容忽視的問題.
目前,對大容量測試數據處理的相關研究已取得較大進展.文獻[2]在Windows XP平臺上使用Labview 8.5圖形化編程軟件、 采用多線程技術實現大容量數據的實時采集、 顯示和分析; 文獻[3]采用分塊處理方式實現對大容量數據文件的處理,并在一定程度上提高了程序的執行效率; 文獻[4]在CVI平臺下使用Windows SDK技術實現了對大容量數據的分析和處理,并使用多線程技術實現軟件可靠、 流暢運行.上述研究均實現了對大容量數據文件的處理,在一定場合下可以滿足用戶的需求.但它們都是通過分塊處理方式來處理、 分析大容量數據中的部分數據,無法反映文件中大部分或所有數據的變化趨勢,另外在處理大容量數據時還存在效率不高的問題[1,3].
本文以裝甲車輛車載測試系統的上位機開發為背景,針對傳統大容量數據預處理方法無法反映數據整體趨勢、 數據處理耗時較長等問題,提出Max-Min抽樣、 內存拷貝、 多線程并行處理等優化方法,在反映數據整體趨勢的同時大幅提高程序的運行效率.
車載測試系統處理大容量測試數據的傳統方法是將數據分塊處理: 使用相關的文件操作函數對原始數據進行定位操作,并結合數據長度實現對局部數據的處理、 顯示.
在測試數據的可視化過程中,使用傳統的抽樣方法(等距抽樣)抽取的數據存在誤差,并且該誤差會隨著數據量的增加被放大.以裝甲車輛振動信號測試為例,對于2 G的測試數據,若振動信號的周期為200 Hz,為使等距抽樣獲取的數據能夠反映數據變化趨勢,則在顯示測試數據的整體趨勢時需要開辟的內存空間約為200 MB.經實際測試,一般的PC設備在同時繪制這么多數據點時會造成程序卡頓甚至卡死.因此,等距抽樣方法無法實現對大容量數據整體趨勢的顯示.
分析傳統大容量數據處理方法時,對數據處理耗時進行實測統計(大容量數據文件是分塊進行處理的,每個數據文件分為173個數據塊進行處理),結果如表 1 所示.
從表 1 可以看出使用常規方法處理數據時,數據抽樣耗時為解碼耗時的3~4倍,讀取數據的耗時隨文件容量的增加近似呈線性增長.隨著測試數據量的增加,傳統數據處理方法的弊端開始顯現出來: 數據量增大到一定程度時,處理數據的時間可能會超出用戶的忍耐限度[3],導致軟件的用戶體驗較差.因此,對大容量數據處理方法進行優化是非常必要的.
針對上述問題提出Max-Min抽樣、 內存拷貝和多線程并行處理方法,其中使用Max-Min抽樣方法顯示大容量測試數據的整體變化趨勢,內存拷貝和多線程并行處理則用于提升數據處理效率.用改進方法處理大容量數據流程如圖 1 所示.

圖 1 改進方法數據處理流程Fig.1 The optimized method of processing data
由于本文處理的數據量非常大,傳統的數據抽樣方法(等距抽樣)已無法準確顯示數據的整體變化趨勢.因此,使用Max-Min抽樣方法來獲取顯示數據,即對數據分塊處理,選取每個數據塊中最大、 最小值反映該數據塊的變化趨勢.采用該抽樣方法獲取的數據量與顯示區域的寬度相關,在無需考慮顯示數據占用內存大小的情況下反映大容量數據的變化趨勢,能夠定位用戶關注的局部數據,以便進一步查看.
測試數據以二進制的形式存儲在磁盤文件中,通過FileStream[5]的Seek和Read函數把數據讀入byte數組中,然后進行數據解碼,即獲取測試數據對應的基元數據類型.C#語言獲取內存中byte數組對應基元類型數據時,常用的方法是調用靜態類BitConverter的ToDouble、 ToInt32等函數.該數據轉換方法的缺點是僅支持對單個對象的操作,處理大量數據時函數調用過于頻繁,數據轉換效率較低.
為提高數據解碼效率,使用內存拷貝方式代替上述數據轉換方法,具體做法是通過調用Buffer.BlockCopy函數,其函數原型如下所示.
public static void BlockCopy(Arraysrc, intsrcOffset, Arraydst, intdstOffset, intcount),其中src表示源緩沖區,srcOffset表示src的字節偏移量,dst表示目的緩沖區,dstOffset表示dst的字節偏移量.Buffer.BlockCopy函數可以實現字節數組和基元類型數組之間的相互轉化,相當于C語言中使用指針訪問基元類型數組,使數據轉化效率得到很大提高.
使用內存拷貝對每個數據塊處理時解碼和采樣消耗的時間如表 2 所示,對比改進之前(表 1)可以看出處理每個數據塊時,數據解碼的耗時明顯減少.

表 2 使用內存拷貝方法處理數據的實測耗時
從表 1 和表 2 中可以看出在數據處理過程中,數據抽樣的耗時占很大比重.通過使用內存拷貝方法,雖然提升了數據解碼的效率,但是對于大容量測試數據的整體處理過程而言,效果仍不明顯,數據處理耗時依然較長.
針對處理大容量測試數據耗時較長的問題,在分塊處理基礎上提出并行處理方法[6].通常情況下,使用并行方法處理任務時,各子任務之間不應存在依賴或順序關系,因為各線程處理結果的輸出順序是不確定的.然而本文將大量數據分配到多個子任務進行處理,這些子任務的處理結果之間存在一定順序關系.
為解決上述問題,使用System.Threading.Tasks程序集中的Parallel.Invoke方法,具體實現過程如下.
1) 定義double類型的數據集合resultData,用于存放最終結果; 同時定義n個double類型的數據集合subResult_1、subResult_2、 …、subResult_n,存放n個線程各自的處理結果;
2) 計算子任務分配時需要的相關信息,主要信息的計算如下所示.

(1)

(2)

(3)
ltn=cn-(n-1)×ptn,
(4)
式中:cn為分割的數據塊數,w為顯示區域寬度,pcl為每個數據塊的數據點數,e和b分別為處理數據的起始、 終止位置,ptn為除最后一個子任務外每個子任務處理的數據塊數,ltn為最后一個子任務處理的數據塊數,n為分配的子任務數;
3) 調用Parallel.Invoke函數,創建多個子任務,并將各子任務的處理結果存放至subResult_1,subResult_2等;
4) 對步驟3)中n個數據集進行整合,將最終結果存放至resultData.
本文實現的多線程并行技術是在雙核、 四線程的PC設備上完成的,該設備在同一時刻最多可以同時執行4個線程.為進一步查看程序中開辟線程數和數據處理時間的關系,圖 2 對分配不同子任務的情況進行對比,從中可以看出: 隨著開辟線程數的增多,處理數據的時間先減少而后增加,分配4個任務處理數據的用時最少.數據處理程序中開辟線程數少于4個時,由于未能充分利用CPU以至數據處理效率不能達到最高; 開辟線程數多余4個時,CPU可能需要在各線程之間切換而增加額外開銷,因此在開辟4個線程處理數據時耗時最少.

圖 2 多線程處理數據用時對比Fig.2 The caparison of elapsed time through multithreading parallel processing technology
在大容量測試數據可視化過程中,使用Max-Min抽樣方法可以反映大量測試數據的整體變化趨勢.從表 1 和表 2 的用時對比中可以看出: 使用內存拷貝方式來處理每個數據塊時,原始數據的解碼時間明顯減少; 同時從圖 1 中可以看出: 使用多線程并行處理技術可以極大地縮短數據處理的整體時間.
優化前后數據處理用時如表 3 所示,可以看出在使用內存拷貝和多線程并行處理的方法后,數據的處理效率有大幅提升,達到60%以上.以處理2 GB的數據文件為例,用戶對圖形顯示軟件操作之后(數據處理方法優化前),等待3~4 s的響應時間是不能忍受的,使用內存拷貝方法和多線程并行處理技術之后將用時降至1 s左右,數據的處理效率明顯提升.本文提出的大容量測試數據處理方法已應用于某裝甲車輛測試系統的上位機軟件中,某通道測試數據經放大后顯示效果如圖 3 所示.

表 3 優化前后處理數據的實測用時對比

圖 3 車載測試系統歷史數據顯示Fig.3 The display of vehicle test system channel data
對于車載測試系統的上位機軟件而言,數據的處理效率是必須要考慮的,尤其在處理大容量測試數據時.本文主要對傳統數據處理方法的進行三方面的改進: ① 采用Max-Min抽樣方法; ② 使用內存拷貝方式來解碼原始數據; ③ 使用多線程并行處理技術來處理大容量數據文件.在顯示大容量數據整體變化趨勢的同時大幅提高數據的處理效率,對于處理大容量測試數據的問題具有參考價值.
然而,本文所提出的處理方法仍存在一定局限: 當待處理的數據量達到4 GB或更多時,用戶在使用軟件時則會感覺到較長延時.處理該問題時需要使用更多的先進技術[7],例如: 內存映射技術[8-9]、 Storm和Mapreduce等大數據處理技術[10],以此進一步提高大容量數據的處理效率,這些是后續工作中需要研究的內容.