程式設計師的 CPU 微架構

轉譯後備緩衝器(TLB)

/ TLB -> tee-el-BEE /

你的程式並不使用真實的實體記憶體位址——它使用虛擬位址,而一個硬體單元會用作業系統維護的分頁表,把每一個虛擬位址轉譯成資料實際所在的實體位址。但走訪那些分頁表要花好幾次記憶體存取,若在「每一次」載入與儲存時都這麼做,將是毀滅性的。轉譯後備緩衝器是一個小而極快的快取,它記住最近的虛擬到實體轉譯,讓常見情況完全略過走訪。

具體而言,記憶體被切成分頁(page,常見 4 KiB)。對你的程式碰到的每一頁,都有一個從其虛擬頁號到實體頁框(page frame)的對映。TLB 在核心旁的硬體裡儲存幾十到幾千個這樣的對映。在一次記憶體存取時,中央處理器到 TLB 查那個虛擬頁:命中就在大約一個週期內回傳實體頁框,存取得以繼續;失誤則表示該轉譯沒被快取,硬體(或作業系統)必須走訪分頁表去找它——這是個慢動作,另行說明。和資料快取一樣,TLB 通常是分開的(一個指令 TLB、一個資料 TLB)且有多層(L1 TLB、L2 TLB)。

程式設計師該在意的原因:TLB 快取的是轉譯、不是資料,而它只涵蓋有限的記憶體量——它的涵蓋範圍是(項目數)乘以(頁面大小)。以 64 個項目、4 KiB 頁面計,單一 L1 TLB 一次只涵蓋 256 KiB 的定址空間。一個跨越許多頁、區域性又差的掃描程式,可能在快取裡資料命中得好好的,卻仍因 TLB 失誤而停滯,因為它碰到的相異頁面比 TLB 能容納的還多。這種 TLB 壓力是真實且常被忽略的代價,而對抗它的主要軟體手段是更大的頁面。

以雜湊(實際上是隨機)頁順序走訪一個 1 GiB 的雜湊表,可能在大多數探查時都產生 TLB 失誤,即使桶的資料本身可快取,因為 1 GiB / 4 KiB = 262144 頁遠遠超過任何 TLB。把表改用 2 MiB 大頁,會把頁數砍掉 512 倍,TLB 失誤也隨之大減。

資料在快取裡卻依然慢:瓶頸是轉譯的涵蓋範圍,而不是資料本身。

TLB 命中不等於資料快取命中——兩者是獨立的。你的資料可能全在 L1,卻仍因 TLB 失誤而停滯,工具也用不同的效能計數器回報它們;別把兩者混為一談。

又稱
TLBaddress-translation cache位址轉譯快取