2002 年 Linux 核心加入 ACPI 支援時 —— 由 Andy Grover 撰寫、Linus Torvalds 提交 —— 其中包含一個「虛擬等待操作」:系統讀取資料並無任何目的,只是為了延遲下一條指令,直到 CPU 能透過 STPCLK# 指令完全停止。在早期,這帶來了省電與相容性,因為當時有些晶片組無法如預期進入閒置狀態。

二十年後,AMD 工程師 Prateek Nayak 提交了一份核心修補程式,以「對基於 Zen 微架構的處理器跳過虛擬等待」。現代 Zen 晶片不需要這種推動,而透過指令取樣進行的測試顯示,這個虛擬操作仍耗費大量時間,而核心卻錯誤地將其計為 C-state 駐留時間。看到這些低負載的工作,CPU 便將自身推入更深、更慢的 C-state,然後需要更長時間才能喚醒 —— 這損害了在忙碌與閒置之間頻繁切換的工作。

測量結果十分驚人:在雙插槽 Zen3 系統上進行的 tbench 測試中,相較於基準核心,修補後的核心最低 MB/s 吞吐量提升了 1,390%,平均 MB/s 提升了 51%,接近完全停用 C2 睡眠狀態的結果。

Intel 系統由於採用基於 MWAIT 的閒置機制,十年來一直避開了這項歷史遺留問題,而 Intel 的 Dave Hansen 提交了一份緊急修補程式,將虛擬等待限制在 Intel 系統上 —— 在那裡它不會影響「相對現代」的機器 —— 並附上評論,敦促讀者改用更現代的閒置機制。由於及時提交,這項修正可能趕上下一週發佈的 Linux 6.0 核心。

一個 2002 年的空操作讀取被電源管理誤判為輕負載的證據,將 Zen 核心推入深度睡眠 —— 刪除它後,最低吞吐量提升了 1,390%。

診斷才是天才之處:指令取樣揭示了被浪費的時間被錯誤標記為健康的睡眠,將一個電源管理記帳錯誤變成了一道明顯的效能懸崖。

這項修正只需一個分支 —— 在 Zen 上跳過虛擬等待 —— 卻能恢復十四倍的最低吞吐量,這是任何對實際工作的最佳化都難以達到的比例。

這是一個技術債的活標本:為 2002 年晶片組加入的程式碼存活了二十年、歷經多個 CPU 世代,因為從未有任何東西故障,它只是變慢了。

相容性補丁的壽命往往超過它們所服務的硬體:除非有人針對新晶片重新審查它們,否則一個二十年前的空操作可能變成隱形的稅負,看起來卻像是晶片問題。

Nayak 的 Zen 修補程式與 Hansen 將虛擬等待限制在 Intel 系統上的緊急後續修補程式,於 2022 年 9 月下旬提交,及時趕上 Torvalds 預期下一週發佈的 Linux 6.0 核心的審議。Intel 的修補程式還加入了鼓勵遷移到現代閒置機制的評論。Ars Technica 報導,修補程式落地後,AMD 系統沒有殘留問題。

追溯依據

參考來源

  1. 20-year-old Linux workaround is still slowing down AMD systems Ars Technica · arstechnica.com ·