軟件性能優化方法匯編


本文主要是對平時工作和Ulrich Drepper的《What Every Programmer Should Know About Memory》中軟件性能優化方法的總結歸納,主要為了方便日后快速查看和檢查,不涉及方法具體細節。本文涉及的軟件性能優化手段包括cache、TLB、預取、多線程、總線帶寬、NUMA等。日后會不定期更新。

cache優化

跳過cache

  • 對於一次性的讀寫操作(比如網卡收發包等),因為數據不會被重復使用,所以沒有必要把數據更新到cache line中,避免換出cache中有用數據。相關方法:_mm_stream_si32/_mm_stream_load_si128等。

L1D cache優化

  • 改進數據局部性,如對於數組,1)把列訪問改為行訪問;2)把大矩陣切分成小矩陣,使數據集為一個cache line大小。
  • 如果CPU支持vectorization特性,使用SIMD (Single Instruction, Multiple Data)操作,提高指令效率。相關方法:_mm_load_sd/_mm_add_pd/_mm_mul_pd等。
  • 保證Critical Word First & Early Restart能最大發揮作用,最先使用的字段(Critical Word)放在數據結構的前面。
  • 按數據結構字段順序訪問字段。
  • 數據結構按cache line字長對齊。相關方法:__attribute((aligned(64)), posix_memalign等
  • 字段保證自然對齊,不要使用pack屬性。
  • 大數據結構拆分成小數據結構。
  • 數組(集中)結構優於鏈表(分散)結構。

L1I cache優化

  • 使用分支預測,以便於編譯器進行代碼局部化優化。相關方法:__builtin_expect或-O2、-freorder-blocks編譯器選項等。
  • 使用小循環代碼塊。
  • 保證代碼對齊。相關方法:-falign_fuctions/-falign_jumps/-falign_loops=cache line字長等。

L2 cache優化

  • 數據集保證在L2 cache大小以內,以便減少L2 cache miss。
  • 對於超過L2 cache大小的大數據集,按L2 cache大小拆分成小數據集。
  • cache着色,解決cache line偽共享問題。(Cache Line 偽共享問題,就是由多個 CPU 上的多個線程同時修改自己的變量引發的。這些變量表面上是不同的變量,但是實際上卻存儲在同一條 Cache Line 里。 )

TLB優化

  • 關閉內核randomize_va_space特性(echo “0” > /proc/sys/kernel/randomize_va_space),減少iTLB miss概率。
  • 減少CPU核超線程個數,例如從4個超線程減少為2個或1個,減少iTLB miss概率。
  • 使用固定TLB映射,例如kmap,減少TLB miss概率。
  • 使用巨頁映射(HugeTLB page),減少TLB miss概率。
  • 減少使用頁面數,減少TLB miss概率。相關方法:減小軟件目標文件大小,減少數據集大小等。

預取優化

  • 關閉內核randomize_va_space特性(echo “0” > /proc/sys/kernel/randomize_va_space),減少branch misprediction概率。
  • 使用靜態鏈接代替動態鏈接,減少branch misprediction概率。
  • CPU自帶的硬件預取。一般情況下功能較簡單,如不支持跨頁,不支持非線性訪問,2+次cache miss后才會觸發等。可酌情關閉,使用軟件預取。
  • 軟件預取。支持跨頁和非線性訪問。相關方法:__mm_prefetch、-fprefetch_loop_arrays等編譯器選項等。
  • 使能CPU OOO(out of order)特性的推測預取。不需要軟件干預。
  • 使用預取線程,要注意多線程同步問題。相關方法:超線程預取等。
  • 使能CPU DCA(Direct Cache Access)特性。不需要軟件干預。
  • 通過gcc自動優化分支預測。相關方法:配置-fprofile_use、-fprofile_generate編譯器選項。

多線程優化

並發優化

  • 分離只讀變量和讀寫變量,減少 false sharing,減少RFO(Request For Ownership)。相關方法:只讀變量用const修飾等。
  • 使用線程本地變量,減少RFO。相關方法:__thread等。
  • 把變量分組集中,並按cache line對齊。相關方法:把只讀變量、讀寫變量分別定義在不同的結構體中。

原子優化

  • LL/SC (Load Lock/Store Conditional)。相關方法:__sync_add_and_fetch等。
  • CAS (Compare-and-Swap)。相關方法:__sync_bool_compare_and_swap等。
  • Transaction Menory。

內存總線帶寬優化

  • 設置線程親和性(thread affinity)。保證工作在不同數據集的線程工作在不同的核上,從而保證L1 cache不共享。

NUMA優化

  • 設置內存親和性策略。相關方法:set_mempolicy等。
  • 設置VMA地址空間親和性策略。相關方法:mbind等。
  • 設置線程的CPU和內存親和性策略:相關方法:cpuset等。

其他

  • 把共享數據轉化為獨享數據。相關方法:對於只讀數據,通過復制;對於讀寫數據,通過先在各node上累加,然后把累加結果再累加得到最終結果。
  • 用度量工具(如massif、memuage等)發現連續分配小內存塊的代碼流程,重構為分配連續地址的大內存塊。
  • 用度量工具(pagein, time等)統計缺頁情況。針對缺頁嚴重模塊改用大頁面以便減少缺頁次數。相關技術:hugetlb等。

 

 --EOF--


免責聲明!

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



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