效能最佳化之CPU快取方法

備忘。

cpu快取由執行速度更快的sram構成,其成本比一般的dram記憶體高許多。因此,cpu快取都比較小,如何利用好這些珍貴的快取記憶體,對於構建一個高效能程式起著至關重要的作用。

cpu快取通常分為大小不等的三級。一、二級快取由單個cpu獨享,三級快取由所有cpu共享。比如,在我的 Linux 系統上,離 CPU 最近的一級快取是 64KB,二級快取是 512KB,最大的三級快取則是 32M。CPU 訪問一次記憶體通常需要 100 個時鐘週期以上,而訪問一級快取只需要 4~5 個時鐘週期,二級快取大約 12 個時鐘週期,三級快取大約 30 個時鐘週期

可以用下面的指令檢視各級快取大小。

cat /sys/devices/system/cpu/cpu0/cache/index0/size

64K

cpu快取有一個CPU Cache Line ,它定義了快取一次載入資料的大小,Linux 上你可以透過 coherency_line_size 配置檢視它,通常是 64 位元組。

一級快取分為資料快取和指令快取。一般可以看到兩個大小一樣的一級快取。

充分利用資料快取,通常把需要連續訪問的資料,放在連續的記憶體空間,並且限制在Cache Line大小的倍數範圍內,有利於提高cpu快取的命中率,進而提升效能。

充分利用指令快取,可以使用 likely 宏顯式幫cpu進行分支預測,提前快取指令。

多核cpu下,為充分利用一級和二級快取,需要減少程序在cpu間切換,Linux 上提供了 sched_setaffinity 方法將程序繫結到cpu上。

多cpu下還會快取一致性問題。資料從記憶體載入到快取記憶體中,以塊為基本單元(一個塊64位元組),相鄰的兩個變數很可能在同一塊中,當這個資料塊分別載入到兩顆cpu的快取記憶體中時,只要一個cpu對該塊(快取記憶體中快取的塊)進行寫操作,那麼另一cpu快取的該塊將失效。可以透過將兩個變數放到不同的快取塊中,來解決這個問題。填充無用位元組也是一個不錯的方式。