摘 要 本文主要針對Intel C++ 9.0編譯器在Visual C++ 6.0環境下對一些常用的功能性操作的優化作用進行了測試驗證。主要從對采用編譯器前後的程序運行時間進行比較來進行判斷。測試范圍主要集中於對線程的切換時間,轉異常以及異常恢復時間,高優先級線程搶先時間以及信號量響應時間方面。此外,還對一些常用的數學函數的運行時間進行了測試比較。得出的測試數據和結論能對采用此編譯器的用戶有一定的參考價值和借鑒作用。
關鍵詞 Intel C++,Visual C++,編譯器,優化
引言
當今許多計算機應用領域,如天氣預報、信號處理以及軍事上的彈道跟蹤等,它們對程序處理速度的要求都是相當高的。否則就會導致結果出現偏差或者失去其意義。要提高程序的運算速度,一般通過以下幾個方面的改進措施來進行:(1)采用新的處理速度更快的硬件設備,如更快的CPU,更大的內存,以及更快的I/O設備等。但這顯然會導致成本的大量增加,並非是一種適合於任何單位的實際的改進措施。(2)更加優化的程序設計方法,如在程序中引入多線程、並行等處理方法。這是一種比較有效的方法,當然對程序設計人員以及編程人員的水平有更高的要求。(3)采用一些優化軟件,這也是一種簡便有效的方法。另外如果和其他兩種方法配合使用,對於一些要求大幅度提高處理速度的場合下,也將是非常有幫助的。
采用優化型編譯器就屬於上面介紹的第三種方法。處理器由於受數據相關、條件轉移和資源沖突等原因,指令級並行度受到極大的限制。通過優化編譯器對指令序列進行重組,以及采用軟件與硬件相結合的方法處理數據相關、條件轉移和資源沖突等,可以大大提高處理器的指令級並行度,使在一定時間內可發射盡可能多的指令數。另外,優化編譯器還能根據處理器中先行指令窗口的大小,把沒有數據相關、控制相關和功能部件沖突,或者沖突和相關比較少的指令調度到同一個先行指令窗口中,使這些指令超越它前面的指令先發射到操作部件中去,從而提高功能部件的利用率,這樣就能進一步提高處理器的性能。
一般來講,實現程序的優化調度需要軟件(主要是編譯器)和硬件的共同結合才能獲得比較好的調度效果。Intel C++ 編譯器作為一款專門針對Intel 型處理器進行優化的編譯器,它們二者的結合從理論上能實現優化調度,能對程序的執行效能有某些方面和一定程度的提高。測試中處理器應選擇Intel系列的產品,實際使用的處理器為Intel 奔騰4處理器(1.8GHZ),內存為256MB;操作系統考慮通用性和廣泛性,為Windows XP系統,編程環境為Visual C++ 6.0。
線程額外開銷測試
針對越來越多的多線程編程應用,線程間的開銷諸如線程間的切換時間、高優先級線程的搶先時間以及線程對信號量的響應時間等指標成為制約程序執行速度的一個重要方面。減少線程的額外開銷時間對提高程序的運行速度是非常有意義的。
1、測試指標
這裡主要包括四個測試指標,(1)線程的切換時間。(2)高優先級線程的搶先時間。(3)信號量響應時間。(4)線程轉異常以及異常恢復時間。
2、測試方法
測試中,啟動的線程開始無條件循環運行。以對指標(1)的測試為例,循環中只進行運行次數累加和線程切換的操作,無其他附加操作,直至給出結束事件,終止線程並給出線程的運行次數和時間。測試的計算結果都是在忽略線程本身的開銷的情況下得出的,這裡線程自身所花費的時間通過測試比較占總花費的時間的比例是非常小的,對計算結果沒有太大的影響。另外若在線程中加入對線程本身開銷的統計,將會引入其他的操作,同樣會有一定的時間開銷,仍然會有誤差存在。測試中對每一個測試項目皆進行五次重復測試,對得出的五個值取平均。
3、測試流程
這裡的測試流程以對指標(1)的測試為例以流程圖的形式加以說明,後面三項的測試與此相似。
4、測試步驟
4.1 線程切換時間測試的基本步驟
(1)創建兩個相同優先級的線程1和2。
(2)運行線程1得到線程1的當前運行次數後,立即切換到線程2。
(3)運行線程2得到線程2的當前運行次數後,立即切換到線程1。
(4)重復第2步和第3步,直到給出結束事件。
(5)得到2至4步所花費的全部時間和兩線程分別的運行次數。
(6)計算線程間的切換時間。
這裡設所花費的時間為emplasedtime,分別運行的次數為runcount1和runcount2,則切換時間為emplasedtime/ (runcount1+runcount2-1)。以下幾項與此類似。
圖1 線程切換時間測試流程
4.2 高優先級線程搶先時間測試的基本步驟
(1)創建兩個不同優先級的線程,假定線程1的優先級高於線程2。
(2)得到線程1的當前運行次數後,線程1將優先級降到低於線程2,線程1被線程2搶先。
(3)得到線程2的當前運行次數後,線程2將優先級降到低於線程1,線程2被線程1搶先。
(4)重復第2步和第3步,直到給出結束事件。
(5)得到2至4步所花費的全部時間和兩線程分別運行的次數。
(6)計算高優先級線程搶先時間。
4.3 信號量響應時間測試的基本步驟
(1)創建信號量1和信號量2。
(2)建有相同優先級的線程1和2,並分別請求獲得信號量1和信號量2。
(3)釋放一個信號量1。
(4)線程1獲得信號量1,得到當前運行次數後,立即釋放信號量2。
(5)線程2獲得信號量2,得到當前運行次數後,立即釋放信號量1。
(6)重復第4和第5步,直到給出結束事件。
(7)得到4至6步所花費的全部時間和兩線程分別運行的次數。
(8)計算線程對信號量的響應時間。
4.4 轉異常以及從異常恢復時間的測試步驟
(1)創建運行一個線程。
(2)在線程中給出一個異常。
(3)異常處理中得出當前異常次數。
(4)重復第2和第3步,直到給出結束事件。
(5)得到2至4步所花費的全部時間和異常產生的總次數。
(6)計算轉異常以及從異常恢復的時間。
5、測試結果
表1 線程額外開銷測試對比
測試項目 線程切
換時間
高優先級搶占
時間
信號量響應時間
轉異常以及從異常
恢復時間
未使用Intel C++編譯器(us)
1.12
2.27
2.38
14.59
使用Intel C++編譯器 (us)
1.09
2.26
2.37
9.21
6、測試結論
從以上四項的測試結果可以看出,除了轉異常以及從異常恢復在使用了Intel C++編譯器後,執行效率有了較大提高(約能提高1/3)外,其他幾項在使用編譯器前後幾乎沒有什麼變化。從這裡可以看出使用Intel C++編譯器編譯的代碼對處理異常時的處理器能有優化效果,執行效率能有較大的提高;對於線程間的響應和切換卻幾乎達不到優化的效果。
數學函數運算測試
前面提到的諸多應用領域,大量的數學運算是必需的。許多程序的主體就是大量的數學運算,運算速度對程序的執行速度也就會有決定性的影響。若能提高數學運算的速度,相應的程序的執行效率就將會得到提高。
1、測試項目
測試項目包括常用的三角函數運算和一些開方、次方、求模、對數等常規運算。畢竟大量的復雜的運算也是由以上運算組合的。
2、測試方法
這裡對每一項的測試都使用相同的測試方法,即讓每種運算都運行固定的大量次數(這裡采用百萬次),得到運行前後的時間值,求出二者之間的差值,即是運行固定次數的時間。再對同一種運算使用Intel C++編譯器進行編譯前後的運行時間值進行比較即可。測試中進行運算的函數參數皆為雙精度型,對於同一種運算在使用Intel C++編譯器前後皆使用相同的參數,避免因帶入參數的不同而影響對比判斷。測試中對每一個測試項目皆進行十次重復測試,對得出的十個值取平均。
3、測試結果
表2 百萬次運算時間對比
測試項目 sin cos tan sqrt pow fmod Log10 未采用Intel C++編譯器 (s) 0.171 0.139 0.228 0.046 0.373 0.262 0.120 采用Intel C++編譯器 (s) 0.054 0.097 0.081 0.031 0.104 0.049 0.062
4、測試結論
從以上對各項數學函數運算所耗時間的測試中可以看出,Intel C++編譯器對數學函數運算的優化效果是比較明顯的。針對不同的運算,優化效果也不盡相同。對於同種運算在使用Intel C++編譯器前後最差的也能將時間縮短至約原來的2/3,最好的能達到約原來的1/5。由此可以看出,若將其用於涉及有較大運算量的程序中,必將較大地提高程序的處理速度,較好的滿足我們在應用中對程序速度的要求。
總結
從以上各項指標的對比測試中,可以得出在減少線程間的轉換開銷方面Intel C++編譯器並不能發揮什麼作用,對於線程本身轉異常以及從異常恢復方面卻能有較大的提高。考慮到異常和中斷處理機制的相似性,我們也可推斷出其對中斷處理效率的提高也應該是有較大作用的。在數學函數運算方面,它能發揮出較大的作用,能較明顯地提高數學函數運算的效率。因此我們認為經Intel C++編譯器編譯過的數學函數運算的代碼能更為高效的執行,這對包含較多數學運算的應用程序來講,Intel C++編譯器的使用將會對程序執行速度的提高提供幫助,從而滿足相關應用領域對處理速度的要求。