我编写了一个内核模块来检查CR4.PCIDE,它没有设置。为什么Linux不使用这样的特性来减少TLB失效和缓存污染造成的性能下降呢?
发布于 2013-11-23 05:23:48
注意:我不是Linux开发人员
对于Intel的“进程上下文标识符”,有4096个ID的限制。这意味着,当有超过4096个进程时,您需要管理它们(例如,可能做一个“最近使用最少”的事情,以便如果一个当前没有ID的进程需要被执行,那么这个ID将从其他进程中取出并重用)。
它的另一件事是多CPU系统上的"TLB射击“。这些东西可能有点贵,所以人们会做些小把戏来避免它们。例如,如果一个进程只有一个线程,那么它只能在一个CPU上运行,并且您知道没有必要向其他CPU发送IPI (中断它们并要求它们执行"TLB射击“)。一旦您开始使用PCID,您就无法确定其他CPU仍然没有TLB条目,也无法通过这些技巧来避免"TLB射击“。这还意味着(在理论上,对于严重实现的PCID支持),您从PCID获得的性能可能低于由于意外的TLB射击和ID管理开销而导致的性能损失,从而造成净损失。
我的主要意思是,添加对PCID的支持有点复杂(不像您只需要在CR4中设置一个标志就可以忘记它)。你必须做一些研究(实验,原型,基准)来确定最有效的方法来实现它。对于一个大型/复杂/旧内核(如Linux),它将更加复杂,因为您必须小心,不要意外地破坏其他东西。另一件事是,这个特性是相对较新的(如果我没有记错的话,它只存在了几年),并且不受许多CPU的支持(例如,任何较老的CPU,以及任何来自AMD的CPU)。
基本上,我假设这可以归结为“时间与好处”(或者,在有限数量的CPU上,没有足够的时间进行小的性能改进)。
发布于 2016-12-31 02:00:01
是的!Linux的最新版本支持PCID。当问到这个问题时,不存在这种支持,但它在2017年底被添加,从4.14内核开始。您可以遵循一些最初的补丁讨论在这个LKML链中。
更改实际上不关联每个进程的唯一PCID,因为每个进程都有有限的数量,或者试图将它们分配给频繁使用的基础,但是每个CPU使用一个PCID缓存,这样在给定CPU上运行的多个进程很可能能够使用PCID机制来避免TLB刷新开销。
这在最近变得更加相关,因为一系列弱点 where发现了它允许非特权用户代码读取内核内存,而KPTI贴片是针对内核内存部署的。这些补丁可能会对性能产生重大影响,因为用户级别的TLB条目在任何内核调用中都可能失效。在支持PCID的情况下,由于保留了用户级别的TLB条目,所以会减少影响.
在发布的内核中无法提供PCID支持时,以下是此答案的旧版本:
还没有,但似乎有什么东西正在酝酿之中。请参阅LKML上启动在这附近的线程。特别是,对跨核心的TLB枪战问题提出了一些解决办法,其中包括:
如果,当接收到非当前PCID的TLB点击率时,我们只是刷新该PCID的所有条目,并从mm的cpu_vm_mask_var中删除CPU,我们将永远不会收到一个以上的非当前mm的射击IPI,但是在处理例如时,我们仍然会得到TLB寿命的好处。管道工作负载,任务轮流在同一个CPU上运行。
您还可以从这个线程中收集地址空间标识符长期以来一直用于其他Linux体系结构的内容。
https://stackoverflow.com/questions/20155304
复制相似问题