我听说TLB由MMU而不是CPU缓存维护。
那么,一个TLB存在于CPU上并在所有处理器之间共享,还是每个处理器都有自己的TLB缓存?
请问有人能解释一下MMU和L1、L2缓存之间的关系吗?
我听说TLB由MMU而不是CPU缓存维护。
那么,一个TLB存在于CPU上并在所有处理器之间共享,还是每个处理器都有自己的TLB缓存?
请问有人能解释一下MMU和L1、L2缓存之间的关系吗?
TLB缓存页面表中列出的翻译。每个CPU核心可以在不同的上下文中运行,具有不同的页面表。每个核心都有自己的MMU,但实际上它根本不是一个单独的单元,而是核心的一部分(装载/存储端口的部分,TLB和页行走器)。任何共享缓存始终是物理索引/物理标记的,因此它们基于后MMU物理地址进行缓存。
TLB是实现细节(PTEs,页面表条目的缓存),可能会因微架构而异;例如386没有TLB,并且为每次加载访问内存多次。实际上,真正变化的只是大小。它始终是每个核心的。现在常见的是两级TLB,以将完整的TLB未命中最小化,同时仍足够小而快,允许每个时钟周期进行3次数据加载/存储翻译(与iTLB并行)。
重新遍历页面表(可以在本地L1数据或L2缓存中热点)以重建TLB条目比尝试跨核共享TLB条目要快得多。这就是避免TLB缺失的极限值的下限,与数据缓存不同,数据缓存是在必须离开核心到共享的L3缓存或L3缓存未命中时才会使用的最后一道防线。
例如,Skylake添加了第二个页行走单元(对于每个核心)。对于逻辑核心无法有用地共享TLB条目的工作负载,良好的页行走至关重要(来自不同进程的线程或不触及许多共享虚拟页面)。
共享TLB意味着invlpg
在更改页面表时使缓存的翻译始终必须离开核心。(尽管在实践中,操作系统需要确保运行多线程进程的其他核心在像munmap
这样的过程中其私有TLB条目被“关闭”,使用诸如IPI(处理器间中断)之类的软件方法进行核间通信。)
但是使用私有TLB,切换到新进程的上下文可以仅设置一个新的CR3(顶级页目录指针),并使该核心的整个TLB无效,而无需打扰其他核心或全局跟踪任何内容。
有一个PCID(进程上下文ID)功能,它允许TLB条目被标记为16个左右的ID之一,因此来自不同进程的页面表的条目可以在TLB中热处理,而无需在上下文切换时刷新。对于共享的TLB,您需要加强这一点。(PCID是每个核心的,因此可以单独为每个核心跟踪最近运行的任务。)
另一个复杂性是TLB条目需要跟踪PTE中的“脏”和“已访问”位。它们通常是PTE的写入穿透缓存。
如果想要了解实际CPU中这些部件是如何组合在一起的,请参阅David Kanter关于Intel Sandybridge设计的文章。请注意,这些图表仅适用于单个SnB核心。大多数CPU中唯一共享的高速缓存是最后一级数据缓存。
Intel的SnB系列设计都使用一个每个核心2MiB的模块化L3缓存,并通过环形总线连接。因此,增加更多的核心会向总池中添加更多的L3,同时还会添加新的核心(每个核心都有自己的L2/L1D/L1I/uop-cache和两级TLB)。