2013-11-22 106 views
21

我寫了一個內核模塊來檢查CR4.PCIDE,它沒有設置。爲什麼Linux不使用這種功能來降低由於TLB失效和緩存污染導致的性能下降?Linux是否將x86 CPU的PCID功能用於TLB?如果不是,爲什麼?

+0

http://forum.osdev.org/viewtopic.php?f=1&t=29935 –

+4

從2017年開始注意:從4.14開始,Linux確實使用它,但方式有點不尋常。 [詳見這裏](https://kernelnewbies.org/Linux_4.14),第1.8段。使用PCID'快速TBL沖洗。 –

+1

剛剛找到'1.10。以上Hi-Angel答案中使用PCID的TLB條目壽命更長,但它非常有用。 – firo

回答

22

更新:這改變周圍的4.15時間表由於Meltdown and Spectre attacks在2017年年底和2018年年初見the other answer瞭解詳情。

注:我不是一個Linux開發人員

對於英特爾的「進程背景標識符」,有4096個ID的限制。這意味着當有超過4096個進程需要管理它們(例如,可能做一個「最近最少使用」的事情,這樣如果一個當前沒有ID的進程需要被執行,那麼這個ID將被從一些其他過程和重用)。

進入它的另一件事是多CPU系統上的「TLB擊落」。這些可能會有點貴,所以人們會花招來避免它們。例如,如果一個進程只有一個線程,那麼它只能在一個CPU上運行,並且您知道不需要將IPI發送給其他CPU(中斷它們並要求它們執行「TLB擊落」)。一旦開始使用PCID,您無法確定其他CPU是否仍然有TLB條目,並且無法執行這些技巧來避免「TLB擊落」。這也意味着(理論上,對於PCID支持執行不力),您從PCID獲得的性能可能會低於由於TLB無故擊落和ID管理開銷而導致的性能損失,從而導致淨損失。

我所說的大部分情況是,增加對PCID的支持有點複雜(它不像你可以在CR4中設置一個標誌,而忘記它)。你必須做一些研究(實驗,原型,基準測試)以確定實現它的最有效方法。對於一個大的/複雜的/舊的內核(比如Linux)來說,它會變得更加複雜,因爲你不得不小心不要讓別的東西不小心弄亂。另一件事是這個功能是相對較新的(如果我沒有記錯的話,這個功能只存在幾年),並且不被許多CPU支持(例如比AMD稍微老一點的東西)。基本上,我認爲它歸結爲「時間與收益」(或者,沒有足夠的時間在有限數量的CPU上進行少量的性能改進)。

+0

16個ID限制來自哪裏?對不起,我沒有得到它。 –

+1

我記得它錯了(它不是16個ID) - 我檢查了,實際上有4096個ID(因爲它是CR3中的一個12位字段)。我改變/更正了我的答案。 – Brendan

+2

您應該總結第一句:** no ** :-) –

11

是的!最新版本的Linux內核具有PCID支持。在問這個問題的時候,這個支持並不存在,但它已經在2017年底附近添加了,從4.14 kernel開始。你可以按照一些原始的補丁討論in this LKML chain

由於數量有限,或者嘗試將它們分配給常用基準,但每個CPU使用PCID高速緩存,因此該更改實際上並未將每個進程的唯一PCID關聯起來,因此幾個正在運行的進程因爲CPU可能能夠使用PCID機制來避免TLB刷新開銷。

最近變得更相關,因爲a series of vulnerabilities發現它允許非特權用戶代碼讀取內核內存,KPTI patches被部署到內核內存。這些補丁可能會對性能產生重大影響,因爲用戶級別的TLB條目可能會在任何內核調用時失效。藉助PCID支持,因爲保留了用戶級TLB條目,所以影響降低了。


舊版本這個答案在下面發現,在這個時候PCID支持在發佈的內核是不可用:

尚未,但似乎喜歡的東西可能是在作品。請參閱LKML上從around here開始的線程。特別是,提出瞭解決方案的交叉核心TLB強行中止的問題,其中包括:

如果接收TLB強行中止對非當前PCID的時候,我們只是 沖洗所有條目爲PCID和從mm的 cpu_vm_mask_var中刪除CPU,我們將永遠不會收到多於一個擊落IPI 非當前毫米,但我們仍然會得到TLB處理例如使用壽命 的好處。管道工作負載,其中任務輪流在 上運行相同的CPU。

您還可以從該線程中收集到地址空間標識符早已在其他Linux體系結構上使用。