優化程序性能常用的幾種方法



> The biggest speedup you’ll ever get with a program will be when you first get it working.
>你能獲得的對程序最大的加速比就是當你第一次讓它工作起來的時候。
—John K. Ousterhout

> ![存儲器山](https://upload.wikimedia.org/wikipedia/commons/thumb/b/b4/MemoryMountain17.png/300px-MemoryMountain17.png)
[存儲器山](https://zh.wikipedia.org/zh/%E5%AD%98%E5%82%A8%E5%99%A8%E5%B1%B1)


* 當然, 一個**程序首先要能運行起來**。 即使是姿勢再丑, 再笨拙,再怎么屌絲, 先讓程序無bug的跑起來再說。

* 選擇**一組合適的算法和數據結構。**算法和數據結構是程序的**靈魂**。

* **編寫出編譯器能夠有效優化以轉換成高效可執行代碼的源代碼。** 對於這一點, 理解編譯器的一些基本能力, 特性以及局限性真的很總要。 編寫程序方式中看上去只是一點小小的變動, 都會引起編譯器優化方式很大的變化。 由於編譯器原理很復雜, 各個編譯器, 以及優化層次選擇的不同, 優化方式可能有很大的變化。 所以,想要編寫出精致高效的代碼, 良好的風格以及不斷的經驗積累才是王道。

* 針對處理運算量特別大的計算, 將一個任務分成多個部分, 這些部分可以在多核和多處理器的某種組合上並行的計算---- **多線程並行算法** 。

程序員必須在實現和維護程序的簡單性與它的運行速度之間做出權衡。



這就是性能

這就是性能!


具體方法


  • 掌握常用的高效的數據結構和算法。 至少要熟悉模板的使用。

  • 消除循環的低效率, 盡量減少循環次數。 盡量不要在循環里 循環計算一些不會改變的值。

  • 消除不必要的存儲器引用。 盡量使用臨時變量來暫存要多次使用的引用值,避免尋址開銷。

  • 防止寄存器溢出。 臨時變量也並不是越多越好, 因為寄存器總是有限的,如果需要同時使用的臨時變量數超過了可用的寄存器數量,編譯器會把臨時值存放到棧中。 一旦出現這種情況, 性能會急劇下降。(x86-64代碼能夠同時累積最多 12 個值, 而不會溢出任何寄存器。)

  • 循環展開。 通俗的說就是利用分治的策略來減小循環的迭代次數。

  • 提高並行性。 大多數情況下,程序的代碼都不是按部就班的一步一步從上往下執行的, 它會適當的並行一些不相依賴的代碼行。 所以盡量編寫不相依賴的代碼, 能夠提高運行效率。

  • 編寫利於分支預測的代碼。 在 CPU 執行分支時, 會預測程序朝哪一個分支方向執行。 如果預測錯誤會被罰時。


    處理方法一般是


    (1): 編寫能被預測的分支。


    (2):書寫條件傳送實現的代碼, 不依賴分支預測。



  • 利用存儲器結構體系 :由於存儲器山的存儲器結構,利用了 時間局部性空間局部性 的代碼, 能極大的提高緩存命中, 從而使程序執行的更快。

  • 多線程編程: 適當的應用多線程, 特別是多CPU的情況下, 程序的性能666的飛起。

  • 多線程 + 線程池: 多線程的進階版本。

  • 參考資料:

    *《深入理解計算機系統》

    *《Java Web Programming》







免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM