姜 悅,褚厚斌,張麗曄,蔡斐華,李 智
(中國運載火箭技術研究院,北京 100076)
隨著計算機多核處理器的迅速普及,軟件架構已經逐漸從傳統的串行模式轉變為并行模式,以充分發揮多核處理器的效率和潛能。多核計算機擁有強大的處理能力,在并行應用領域有著廣闊的應用前景,多線程編程技術已成為當前重要的軟件技術之一。
在航天運載領域,匹配試驗結束后,試驗數據后處理解析軟件需要將保存下來的dat 格式的遙測原碼,通過挑幀、十進制轉換、公式轉換、寫入文件等處理方法,轉換成物理量值供各系統進行判讀評估,并進行受控。普通的單線程數據后處理解析能夠按照幀協議的格式將遙測原碼解析,并進行文件寫入,但數據文件寫入遲滯,導致主線程阻塞,效率不高。如何快速、高效、可靠且準確地寫入數據文件是后處理解析軟件的核心任務。
多線程是現代操作系統中非常重要的概念。多線程即允許同時執行多個線程,對完成并行任務和提升用戶體驗非常重要。在傳統的操作系統中,進程通常指代正在運行的程序的實例,每個進程都有自己的地址空間和一個執行線程,該線程通常叫做主線程[1]。在同一進程環境中可以執行多個線程,一般而言,運行在同一個進程中的多個線程具有相同的地址空間。線程是進程中的實際運作單位,是操作系統分配處理器時間的基礎單元,它們彼此合作、交流,共享該進程中的全部系統資源,如處理器時間、內存和變量等[2]。
多線程設計中最重要的一個環節就是識別軟件中的可并行部位,并對該部位進行問題分解,即將軟件劃分為多個獨立的任務,并確定這些任務之間的相互依賴關系。
問題分解的方式主要有三種[3]:
(1)任務分解:將不同的行為分配給不同的線程,需要移除任務間的依賴性或使用復制來分離依賴性。此種方式需打破原有程序的邏輯關系,消除任務間的依賴性,適用于任務多且并行度高的問題。
(2)數據流分解:將計算分割成一系列階段,每個線程在不同的階段同時工作。此種方式不破壞原有程序的邏輯關系,適用于邏輯性強的問題,但數據流影響程序并行執行能力,易出現線程空閑。
(3)數據分解:分割數據集,多個線程對不同的數據集執行同樣的操作。此種方式不破壞原有程序的邏輯關系,適用于數據多且格式規范的問題。
試驗數據后處理解析軟件通過讀取試驗過程中存儲的遙測原碼,根據XML 文件中的協議、幀結構、參數和公式的配置信息,完成數據的解析,并以文本形式存儲。后處理解析執行過程如圖1 所示,包括讀取數據原碼、類型判斷、獲取主幀、幀解析、獲取子幀、公式轉換、格式處理及文件寫入7 個主要模塊。

圖1 幀數據處理過程圖Fig.1 Flow diagram of data processing
(1)讀取數據原碼
軟件首先對文件進行檢測,確認文件格式,識別文件類型,然后逐幀讀取遙測原碼文件。
(2)類型判斷
軟件對讀取的一幀原碼幀進行幀頭識別和幀類型判斷,以確定合理的解析方式。
(3)獲取主幀
獲取主幀主要從數據流中完成整幀的提取,采用判斷幀頭和幀長度的方式獲取整幀,然后再對幀中的參數進行解析。
(4)幀解析
幀解析功能主要是根據參數的波道位置和占字節數從幀緩存區將參數存儲的十六進制數據取出,并根據數據類型轉換成十進制。
(5)獲取子幀
挑包功能應用于主幀中有嵌入子幀(異步幀)的協議,在完成主幀解析后,繼續獲取主幀中的嵌入子幀,獲取嵌入幀采用判別幀頭、幀長度和幀尾的方式獲取整幀,對沒有幀尾的子幀,采用判別幀頭、幀長度和下一幀頭的方式獲取整幀,該種判別子幀的方式可以過濾掉半幀的情況。
(6)公式轉換
遍歷幀參數結構中的所有參數,根據參數代號從公式轉換庫中查詢該參數的物理量轉換公式,將參數的十進制數轉換為物理量值,重新存入參數結構中。在完成公式轉換后,將得到由參數物理量值組成的不同解析幀。
(7)格式處理及文件寫入
在格式處理及文件寫入階段,軟件按照數據處理格式要求,對解析幀完成寫入數據的格式轉換,以及時間和物理量值的拼接,然后將結果寫入參數文件。
在單線程架構下對圖1 所示的后處理過程中各模塊進行時間插樁,采集各模塊的運行時間,分析結果如圖2 所示。可以看出,模塊①~⑥運行的總耗時與模塊⑦運行的總耗時比例約為1 ∶13,同時考慮到模塊①~⑥邏輯關系強,并行度低,模塊⑦并行度較高,因此將關鍵因素定位為“格式處理及文件寫入”模塊,進行多線程算法設計。

圖2 單線程架構分析圖Fig.2 Analysis of single-thread architecture
考慮到后處理解析具有邏輯性較強,數據較多且格式規范等特點,采用基于數據分解的問題分解方式,對本問題的模型適用度更高,且應用至不同型號時無須重新進行邏輯分析,可擴展性強。因此,本設計采用基于數據分解的后處理多線程設計,即將每個解析幀結構按CPU 核數進行分割,將分割后的數據塊分配至不同的CPU 核進行處理,如圖3 和圖4 所示。

圖3 系統設計框圖Fig.3 Design diagram of system

圖4 多線程后處理解析方法示意圖Fig.4 Diagram of multi-thread method for test data post-processing parsing
多線程的執行通常存在著無序性,而試驗數據后處理解析過程對參數文件的寫入要求嚴格有序,保持原有的時間序列。因此,在任務分配時需要考慮不能有兩個及以上的線程同時向同一參數文件進行寫入操作。在任務分配方式設計時采用基于定向和閑置混合的方式,即當分配當前時刻的幀結構片段時,如果上一時刻的該幀結構片段仍在被某個線程進行處理,則采用定向分配原則;否則,采用閑置分配原則。這樣既可以保證參數寫入的準確度,又可以達到各線程負載均衡。線程調度數據結構如表1 所示。

表1 線程調度數據結構Tab.1 Data structure of thread scheduling
具體規則為:
(1)識別跨包參數:如果同一個參數出現在不同包幀協議中,應予以識別并標識,不能采用多線程方式解析;
按參數個數將一幀解析幀(解析幀數據結構如表2 所示)拆分為獨立的等長度的幀結構片段,分配給不同核上的線程,每個線程處理不同的幀結構片段,能夠達到將多線程負載盡可能均衡地分配在不同CPU 內核上的目的。

表2 解析幀數據結構Tab.2 Data structure of parsing frame
具體規則為:對于跨解析幀參數所在的解析幀,不進行拆分;對于不含跨解析幀參數的每一類解析幀,將其按參數個數等分為n-1 段,其中n為CPU 核數。采用下取整對參數個數進行拆分,相同解析幀類型只拆分一次,后續不再拆分。
在主線程和子線程之間建立緩存隊列,可以實現主線程和子線程并行工作,有效提高主線程和子線程的工作效率。緩存隊列采用環形隊列結構,數據結構和示意圖分別如表3 和圖5 所示。相較于普通隊列,環形隊列能夠有效利用資源,避免假滿隊列的情況出現,空間利用率更高。其方法為:

表3 緩存數據結構Tab.3 Data structure of cache region

圖5 環形數組示意圖Fig.5 Diagram of annular array
(1)確定環形隊列在算法中的使用部位:用于主線程和各子線程之間的共享數據緩存,即各幀及幀片段的解析結果。
(2)完成環形隊列數據結構設計,利用head 作為環形數組的頭部標識,tail 作為環形數組的尾部標識。
(a)入隊:先判斷tail 節點的下一個位置是否是head,如果是,就表示隊列已滿,無法入隊;如果不是,就可以入隊,即將元素放入tail 的下一個位置,最后將tail 加1(為了能夠在tail 增加到數組尾部時能夠轉回到首部,這里需要將tail 加1 與隊列的大小取余再賦值給tail);
(b)出隊:先判斷tail 和head 是否相等,如果相等,就表示隊列已空,無元素可出,不等則表示非空。此時需要取出head 對應位置的元素,然后將head 加1(為了能夠在head 增加到數組尾部時能夠轉回到首部,這里需要將head 加1 與隊列的大小取余再賦值給head)。
同時,多線程在設計時需要保證共享數據操作的完整性,即保證在任一時刻,只能有一個線程訪問該對象。通過對資源池進行分析,將需要上鎖的資源定位于環形隊列,在鎖定與解鎖資源時遵循以下原則:
(1)當更新對象域的時候總是鎖定;
(2)當訪問可能更新的對象域的時候總是鎖定;
(3)當調用其它對象方法的時候總是鎖定;
(4)資源使用完畢后及時解鎖,釋放資源。
在多線程技術中,用戶需要根據任務或程序的需要創建線程。創建解析線程分為以下幾步:
(1)創建主線程,流程如圖6(a)所示;
(2)在程序中為每個核創建一個線程;
(3)主線程和子線程同步執行,子線程聽從主線程分配任務,流程如圖6(b)所示。
選取某型號試驗數據后處理解析軟件,分別形成單線程參考版本和多線程測試版本,在單CPU 八核電腦上對多線程功能進行測試,基于單線程運行結果,對多線程性能及結果進行評估,多線程性能測試環境如表4 所示。

表4 多線程性能測試環境Tab.4 Muti-thread performance test environment
經測試,多線程的加速比和CPU 利用率效果對比如表5 所示??梢钥闯?通過在不同數據源下對多線程模塊進行測試,在單CPU 八核電腦上算法加速比不低于49%,CPU 利用率提升不低于260%。

表5 多線程測試結果Tab.5 Muti-thread test results
通過對多線程的遙測原碼后處理解析的關鍵技術進行研究,采用多線程技術優化后處理軟件,可得到較顯著的性能優化。經多線程設計改進后,該軟件具有較高的執行效率,在多核處理器上能夠充分發揮計算機性能,達到顯著提升試驗數據處理效率的目的。