帶著10萬字的草稿,C++優化系列來了!
本文轉載自微信公眾號「程序喵大人」,作者程序喵大人。轉載本文請聯系程序喵大人公眾號。
大家好,我是程序喵。
不知不覺又到周一了,你是不是還在床上?看到這條推送的時候,如果你已起床,請在評論區扣1,讓程序喵看看有多少人和我一樣勤奮!最近C++技術交流群發現了很多水平很高的朋友,歡迎大家來加喵哥微信,進群一起討論計算機知識!
近期我會推出一系列C++優化文章,可能因為要過年的原因,發現最近閱讀量明顯下降,所以硬核系列文章會在年后更新,這篇文章先吊一吊大家胃口,作為引言吧。
我們平時編寫工程程序時,除了功能可用性外,性能也是最主要的考慮因素。編寫功能可用的代碼很容易,往往難到我們的不是實現某個功能,困難的永遠是保證功能可用的同時又能滿足對性能的要求。
一般公司對程序的體積以及運行速度都有嚴格的要求,有時候因為幾字節的代碼段體積或者多了幾十毫秒的運行時間,整個項目就達不到驗收標準,導致不能成功上線。說了這么多只是為了突出性能優化的重要性。如何做好優化才能體現一個C++程序員的真正水平。
關于性能優化,有三個概念我們需要了解:
1. 性能指標要靠測量,不能靠猜:
我做過一段時間的SDK開發工作,每當我們發版SDK時候,都要附帶著SDK使用文檔以及性能測試報告,性能測試報告里面有很詳細的指標測試數據,這個數據當然不能是自己猜測出來的,一定要進行測試。
2. 帕累托法則
帕累托法則,也稱二八原則,80%的執行時間花在大約20%代碼身上,80%的內存被大約20%的代碼使用,80%的維護成本花在20%的代碼上面。我們做程序優化也是如此,多數情況下也許我們只需要找到那20%代碼,對其進行深度優化,基本上就可以滿足性能要求。
3. 阿姆達爾定律
SPRING
阿姆達爾定律:有一個公式,公式中:St表示優化后整體性能提升的比例,P表示被優化部分運行時間占總運行時間的比例,Sp表示被優化部分性能提升的比例。
舉個例子:
1. 程序運行時間100s,其中有90s調用函數func,func優化后性能提升30%,即P=90/100=0.9,Sp=1+30%=1.3,則程序整體效率為St=1/((1-0.9)+0.9/1.3)=1.26214,程序整體性能提升了26%。
2. 程序運行時間100s,其中有10s調用函數func,func優化后性能提升80%,即P=10/100=0.1,Sp=1+80%=1.8,則程序整體效率為St=1/((1-0.1)+0.1/1.8)=1.04651,程序整體性能提升了4%。
該定律其實也間接驗證了帕累托法則的正確性,去優化那些至關重要的部分吧。
聊完了性能優化的原則,再來說下我的優化系列規劃吧,目前打算優化大體分為以下幾個專題:
1. 測量分析專題:例如使用什么函數來測量函數耗時,使用什么代碼分析工具來動態和靜態的分析代碼。例如:
2. 編碼規范專題:分析C++各種操作的效率,包括不同類型變量的存儲效率,使用智能指針、循環、函數參數、虛函數、數組等的效率,以及如何更好的利用他們進行代碼優化。例如各個操作占用的時鐘周期:
3. 編譯優化專題:各種編譯器性能分析,理解常見的編譯優化選項,分析編譯器是如何對代碼進行優化的,都做了什么優化,以及編譯器優化的障礙(它不能做什么),如何充分利用好編譯器的優化選項。例如優化編譯器優化級別介紹:
O0(默認選項):不開啟優化,方便功能調試
Og:方便調試的優化選項(比O1更保守)
O1:保守的優化選項,打開了四十多個優化選項
Os:產生較小代碼體積的優化選項(比O2更保守)
O2:常用的發布優化選項,在O1的基礎上額外打開了四十多個優化選項,包括自動內聯等規則
O3:較為激進的優化選項(對錯誤編碼容忍度最低),在O2的基礎上額外打開了十多個優化選項
Ofast:打開可導致不符合IEEE浮點數等標準的性能優化選項。
如圖:
4. 內存優化專題:內存使用情況往往是影響程序性能的關鍵因素,該專題會介紹如何有效利用緩存,如何操作緩存,優化內存訪問速度,如何使用更少的內存,如何防止內存抖動,內存對齊等等。
5. 多線程優化專題:如何充分利用CPU,如何做好線程同步,如何使用鎖,使用什么鎖,理解和調試上下文切換,如何使關鍵線程運行效率更高等等。
6. 亂序執行專題:理解CPU的亂序執行策略,如何利用此特性寫出高效代碼。
7. 矢量運算專題:理解CPU的矢量運算以及各種指令集、寄存器以及內置函數,提高數據計算的效率。
8. 特殊的優化編碼技巧:這里會介紹很多高效的編碼技巧,如何降低分支預測率,如何優化低效的除法操作,如何更好的進行數據邊界檢查,介紹一些高效的數學函數庫等等。
9.模板元編程的編碼技巧:如何利用模板編程來優化程序運行效率。
10.大雜燴:其它一些實用小技巧。
介紹到這里,向大家推薦個好用的網站鏈接,第一個是:https://godbolt.org/
點擊查看高清圖片
如圖,輸入C++代碼,在右半部分會顯示編譯器編譯后的匯編代碼,通過查看高級語言背后的匯編指令我們可以更好的分析代碼的性能。網站更強大的功能是它支持市面上幾乎所有的編譯器,而且各個版本都有。
如果我們看匯編代碼比較吃力,那可以上這個網站:
https://cppinsights.io/
如圖,該網站右半部分會展示編譯器眼中的代碼,對于我們分析程序也有很大幫助。