4.3. 最佳化分页表存取

分页表的所有资料结构都会被保存在主memory中;操作系统就是在这里建构并更新表格的。在一个行程的创建、或是分页表的一次修改之后,都会立即通知 CPU。分页表是用以将每个虚拟地址,使用上述的分页表走访来转成实体地址。更准确地说:每一层至少会有一个目录会被用在转换一个虚拟地址的过程中。这需要高达四次memory存取(以执行中行程的一个单一存取而言),这很慢。将这些目录表的项目视为普通的资料、并在 L1d、L2、等等cache它们是办得到的,但这可能还是太慢了。

从最早期的虚拟memory开始,CPU 设计者便已采用了一种不同的最佳化。一个简单的计算能够显示,仅将目录表的项目保存在 L1d 以及更高层级的cache中会招致可怕的效能。每个独立的地址计算会需要相符于分页表深度的若干 L1d 存取。这些存取无法平行化,因为它们都依赖于前一次查询的结果。单是这样就会 –– 在一台有著四个分页表阶层的机器上 –– 需要至少 12 个周期。再加上 L1d 错失的机率,结果是指令管道无法隐藏任何东西。额外的 L1d 存取也需要将宝贵的频宽偷到cache去。

所以,不只是将目录表的项目cache起来,而是连实体分页地址的完整计算结果也会被cache。跟程序码与资料cache行得通的理由相同,这种cache的地址计算结果是很有效的。由于虚拟地址的分页偏移量的部分不会参与到实体分页地址的计算,仅有虚拟地址的剩馀部分会用来作为cache的标籤。视分页大小而定,这代表数百或数千条的指令或资料物件会共享相同的标籤,因而共享相同的实体地址前缀(prefix)。

储存计算得来的值的cache被称为转译后备缓冲区(Translation Look-Aside Buffer,TLB)。它通常是个很小的cache,因为它必须非常快。现代的 CPU 提供了多层 TLB cache,就如同其他cache一样;更高层的cache更大也更慢。L1TLB 的小容量通常借由令cache为全关联式、加上 LRU 逐出策略来弥补。近来,这种cache的大小已经持续成长,并且 –– 在进行中 –– 被转变为集合关联式。因此,当一个新的项目必须被加入时,被逐出并取代的项目可能不是最旧的一个。

如同上面所注记的,用来存取 TLB 的标籤为虚拟地址的一部分。若是在cache中有比对到标籤,最终的实体地址就能够借由将来自虚拟地址的分页偏移量加到被cache的值上而计算出来。这是个非常快的过程;它必须如此,因为实体地址必须可用于每条使用独立地址的指令、以及 –– 在某些情况下 –– 使用实体地址作为键值(key)的 L2 查询。若是 TLB 查询没有命中,处理器必须要进行一次分页表走访;这可能是非常昂贵的。

透过软件或硬件预取程序码或资料时,若是地址在另一个分页上,能够暗自预取 TLB 的项目。这对于硬件预取而言是不可能的,因为硬件可能会引发无效的分页表走访。程序开发者因而无法仰赖硬件预取来预取 TLB 项目。必须明确地使用预取指令来达成。TLB –– 就像是资料与指令cache –– 能够出现在多个层级。就如同资料cache一样,TLB 通常有两种:指令 TLB(ITLB)以及资料 TLB(DTLB)。像是 L2TLB 这种更高层级的 TLB 通常是统一式的,与其它cache的情况相同。

results matching ""

    No results matching ""