本章节重点内容为2、3、4、5四个小节,理解难度较大。
本章将简要介绍当前多核体系结构下的存储层次。在多核体系结构中,存储层次由硬件管理的临时存储(如Cache),以及少量采用软件管理的临时存储(如便笺式存储器)组成。本章将主要介绍高速缓存体系结构基础,包括常见的概念、高速缓存的组成, 特别是针对多核体系结构的高速缓存组成。本章的最后将针对当前多核系统中的高速缓存组成进行案例分析。
知识点:
5.1存储层次的意义
提高程序性能的关键是保证CPU大部分的数据访问时延较低,这正是高速缓存设计的初衷。
高速缓存是一个相对较小的存储单元,用于保存可能会被指令访问到的数据。
如果数据的访问是完全随机的,那么每一级高速缓存的命中率(访存请求中数据位于高速缓存的比例)与高速缓存大小和程序工作集大小的比率成正比(对于小缓存而言,这个比例非常小),然而,高速缓存命中率通常远高于随机访问的情况,L1和L2高速缓存命中率达到70%〜95%的情况并不少见。
5.2高速缓存体系结构基础
为了发掘空间局部性并减少管理开销,一个缓存行 (cache line)中的多字节(也称为缓存块,cache block)会被同时读取,类似于表格中的一个单元格。表格的基本参数包括行数、列数和单元格大小。相应的,高速缓存的基本参数包括组数、相联度(路数)和缓存块大小。高速缓存的大小(简称缓存大小)等于组数、路数和缓存块大小的乘积。相对于缓存组数而言,缓存大小对程序性能具有更加直接的影响,因此高速缓存参数通常由缓存大小、路数和缓存块大小确定。
高速缓存的管理需要考虑三个方面:
首先是数据放置策略,用于确定存储块在高速缓存中的放置位置;
其次是数据替换策略,用于在高速缓存不足时确定被替换岀缓存的数据块;
最后是数据写策略,用于确定缓存块的写时机以及新写入的值传播到外层存储的时机。
髙速缓存的组数和路数组织方式决定了数据块的放置方式。
(1)数据放置策略
高速缓存中定位数据块的步骤:
1)确定数据块映射的组。
2)访问缓存组以确定访问的数据块是否包含在该缓存组内,如果包含则访问该数据块。
3)访问相应的数据块,选择请求的字节或者字,并将其返回给处理器
确定数据块映射的组(第一步)是通过缓存索引函数实现的。通常来说,缓存索引函数都比较简单,例如,组的索引可以通过对数据块地址和组数取模获得: setldx = blkAddr mod numSets (取模函数)
几种常见的索引策略:
①简单的取模索引
传统的缓存索引方法要求组数为2的幂,因此上述的取模函数只需要抽取地址低位中的若干位(即索引位),不需要任何计算就可以获得组索引。需要注意的是,由于主存大小要远远大于高速缓存,因此可能会有多个存储块被映射到同一个组。当一个数据块保存在高速缓存中时,需要记录保存的是哪一个数据块,从而当有请求访问数据块时可以确定该数据块是否保存在缓存组中。被映射到同一个组的多个数据块地址具有相同的索引位,因此在保存数据块的同时,需要保存除了索引位和块偏移之外的其他位,这些位被称为标签位。对 于简单的取模索引函数,块地址中除了索引位之外的其他位就是标签位。
简单的取模索引可以保证存储中连续的数据块被映射到不同(且连续)的组内,这种映射方式有助于将存储数据块均匀地放置在缓存组内。索引所需的位数取决于高速缓存中的组数。例如,如果高速缓存中有2048个组,那么正确定位每一个组则需要log2(2048)= 11位。
②质数取模索引
在一些情况下,访存模式以2的幕次方的倍数为间隔访问地址,这会导致地址被更多地映射到特定的一些组内,而另一些组被映射得很少,使得缓存组的利用不均衡。另一种策略则是使用非2的幂次方的组数,特别是使组数为质数,这种索引函数被称为质数取模索引。
例如,在高速缓存中设置2039而非2048个组( 2039是最接近2048的质数)。下图展示了这种索引函数。质数取模索引需要基于整个数据块地址空间进行设计,并且整个数据块地址空间需要被存储在每个数据块的标签内。
③高速缓存索引
高速缓存索引函数的另一种可能是通过对数据块地址的不同部分进行异或操作从而产生伪随机数作为地址(上图的底部 XOR部分)。与质数 取模索引相似,基于异或操作的索引也需要将整个数据块地址空间存储在标签内。总体上讲,质数取模和基于异或操作的索引都可以在很大程度上减少缓存组的不均衡利用。然而,获取索引需要额外的计算开销, 设计者需要比较开销和收益从而选择出一款适合的索引函数。
高速缓存索引定位数据块的过程:
①在标签阵列中访问数据块可能被映射到的组。
②组内的两个标签被传送到传感放大 回 器(SA)中。
③并且与请求地址的标签进行比较。
④在步骤2和3执行过程中,两路中的数据块被读出到传感放大器中。
⑤如果任何一个标签可以匹配,则是高速缓存命中,否则是高速缓存缺失。当出现任意一路的标签匹配时,同一路上的正确数据块会被选中。
⑥最终,请求的字节/单个字/多个字通过地址中的块偏移位被选中。
⑦并返回给处理器。
④路预测技术
路预测技术利用一个给定了数据块地址的较小的表格, 可以预测该数据块存储在高速缓存中的路。当预测结果准确时,可以在标签和数据阵列查找中同时发挥串行查找和并行查找的优势。例如,通过路预测技术,步骤1、2和4可以并行执行。不同的是,步骤4中的数据阵列查找只在被预测的路上执行,并不会读取其他路上的数据。因此,标签和数据阵列查找可以并行执行。步骤3通过对比缓存标签和数据块地址的标签,既可以确定是否高速缓存命中,又可以确定路预测是否正确。如果路预测正确,那么就已经获得了相应的数据块,所需的字节被返回处理器;若路预测不正确,那么已经读取的数据块为错误的数据块,需要在正确的路上重新执行一遍数据阵列查找。在预测正确的情况下,采用路预测技术可以在高速缓存查找时获得像并行查找一样的速度,以及如串行查找一 样的功耗;如果预测错误,高速缓存将消耗更多的功耗,并且花费比串行查找更长的时延。 准确的路预测方法对于该技术产生较高的性能至关重要。
(2)数据替换策略
定义:对于组相联的高速缓存,当有一个新的数据块从外层存储层次中被读入高速缓存时,如果此时高速缓存已满,则需要将已经缓存的一个数据块替换出高速缓存。
评价高速缓存数据替换策略优劣的标准:被替换出的数据块应该是将来最晚被访问的数据块。然而,最优的高速缓存替换策略虽然从理论上可以保证产生最少的高速缓存缺失,但是由于其需要未来的访存信息,在实际中并不能完全实现。
大部分的高速缓存实现都采用了最近最少使用(Least Recently Used, LRU)或者与其近似的替换策略。在LRU替换策略中,当有新的数据块需要空间时,过去最远时间内被访问过的数据块将会被替换出高速缓存。LRU替换策略利用了代码的时间局部性,即最近被访问的数据在未来也会被访问。实践证明,即使在有些情况下与最优替换策略差距较大,在大多数情况下LRU表现较好。在一种情况下,LRU 的性能较差,即程序以循环的方式访问大于高速缓存可以存储的数据块。例如,程序访问数据块A、B、C、A、B、C、A等。如果所有的数据块都映射到同一个缓存组,同时该高速缓存为两路组相联,则每个数据块访问都会导致缓存缺失。
LRU的实现方式
①利用位矩阵并将其存储在标签阵列中保存LRU信息的部分。在这种矩阵形式的实现方式中,行和列的数量与高速缓存的路数相同,每个行和列都与特定的路相关联。下图展示了这种实现方式。假设开始时一个4路相联的高速缓存组包含数据块A、B、C和D,访存的序列为B、C、A和D, LRU矩阵初始化全部为 0。其中,LRU矩阵为4 x 4矩阵。每次缓存命中特定的路后,将会更新矩阵中该路对应的行的所有位为1,同时更新该路对应的列的所有位为0。
②一种可能的近似LRU的方法是记录最近最常访问的一部分数据块,当需要替换时, 那些未被记录的数据块通过随机或者特定的算法被替换出高速缓存。这种方法的一个最简单的例子就是记录最近最常使用(Most Recently Used, MRU)的数据块,当需要替换时,通过伪随机算法选择非MRU的数据块替换出高速缓存。下图中展示的基于树的伪LRU替换策略。
(3)数据写策略
高速缓存设计中面临的一个重要问题是当处理器修改了高速缓存中的数据后,这些修改什么时候被传播到外层的存储层次。实现中有两种选择:写直达和写回。
①在写直达策略中,高速缓存中任何一个字节的修改都会被立刻传播到外层的存储层次。
②在写回策略中,修改并不会立刻传播到外层的存储层次。只有当缓存块被替换时,这些被修改的数据块会写回并覆盖外层存储层次中的过时数据。
写直达策略与写回策略的对比:
①由于在高速缓存中的数据块会被多次写入的原因:写回策略倾向于节省高速缓存和外层的存储层次之间的带宽;写直达策略中,每次写都会消耗带宽以将写入的值传播到外层的存储层次。
②对于处理器芯片最外层的高速缓存,由于片外带宽非常有限,因此往往采用写回策略;而对于内层高速缓存,由于片上带宽较大,因此往往釆用写直达策略。
③一个影响写回和写直达策略选择的因素是在硬件故障下的容错
在写直达策略中,当检测到故障时,可以安全地丢弃出故障的数据块并从外层存储中重新读取该数据块。然而在写回策略中,仅仅只有故障检测并不充足。因此,采用写回策略的高速缓存不仅仅需要错误检测,也需要错误纠正。
④另一个影响写直达和写回策略选择的关键因素是外层高速缓存的功耗, 因为每一次对内层高速缓存(如L1高速缓存)的写都需要被写入外层高速缓存。
写分配与写不分配:
数据写策略的另一方面(写分配和写不分配):确定当要写入字节/字的数据块不在高速缓存中时,是否将其读入高速缓存中。
写分配(Write Allocate, WA)策略:在写缺失时,写分配策略会在写入数据块前将其读入高速缓存。
写不分配(Write No-Allocate, WNA)策略:将要写入的数据直接传播到外层存储层次而并不将数据块读入高速缓存。
写分配与写不分配的应用条件:
①当数据块中相邻的字节在未来被读写的概率较低时,即当写后的空间局部性较差时,写不分配策略的性能较好。当数据块中被写入的字节在未来被读写的概率较低时,即当写后的时间局部性较差时,写不分配策略的性能也较好。
②如果数据块中被写入的字节或者相邻的字节在未来被读写的概率较高时,则写分配策略的性能较好。当增加缓存块的大小时,该缓存块被多次访问的可能性也会增加,因而在缓存块较大时,写分配策略的性能要优于写不分配策略。
③写直达策略可能使用写分配策略或者写不分配策略。但一个写回高速缓存通常会使用写分配策略。其原因在于,如果不使用写分配策略,写缺失会被直接传播到外层存储层次,变得与写直达高速缓存相似。
(4)多级高速缓存中的包含策略
多级高速缓存的设计中,一个相关的问题是内层高速缓存(容量较小)的内容是否包含在外层高速缓存(容量较大)内。
三种包含策略:
①包含(inclusive):如果外层高速缓存包含了内层高速缓存的内容,则称外层高速缓存为包含的(inclusive),或者具有包含属性。
②排他(exclusive): 如果外层高速缓存只包含不在内层高速缓存中的数据块,则称外层高速缓存相对于内层高速缓存是排他的(exclusive)。
③既不包含又不排他(Non-Inclusive non-Exclusive, NINE):包含性和排他性需要特殊的协议才能实现,否则包含性和排他性都无法保证,这种情况有时被称为既不包含又不排他(Non-Inclusive non-Exclusive, NINE)。
下图在不同列中展示了不同策略的差异。图中的高速缓存为两级,其中L2高速缓存可以是包含的、排他的,以及既不包含又不排他。
不同包含策略的优缺点分析:
优点:
①数据安全且效率高。釆用包含策略的高速缓存具有一个重要的特点,即所有存储在内层高速缓存的数据块也存储在外层高速缓存。
②缓存缺失的时延较短。
③对所有内层高速缓存检查访问的数据块是否存在意味着增加对高速缓存控制器和内层高速缓存标签阵列的占用。
缺点:
①实现包含策略需要付出一定的开销。
②对比排他和NINE策略,采用了排他策略的高速缓存不会在内层高速缓存中保留冗余的数据块,因而其可以存储更多的不同数据块。相反,采用了NINE策略的高速缓存只会在出现缓存缺失时才会填充新的数据块。因此,采用了排他策略的高速缓存会消耗更多的内外层间缓存带宽,并且对标签和数据阵列产生更高的占用率。
③在共享最后一级高速缓存的多核体系结构中,包含策略的存储开销是巨大的。
(5)统一/分立/Banked高速缓存和高速缓存流水线
高速缓存设计的另一个重要目标是高访问带宽。
如果高速缓存在一个时钟周期内支持多个并发访问,那么就需要提供较高的访问带宽。对于统一高速缓存(unified cache),提供如此高的带宽需要包含至少两个读端口和一个写端口。高速缓存中每多出来一个端口就意味着要增加额外的解码器、字行的连线、位行的连线、传感放大器和多路复用器。对于一个两端口的高速缓存,其物理结构比一个端口的高速缓存大很多。同样,对于一个三端口的高速缓存,其物理结构比两端口的高速缓存大很多。高速缓存结构较大会增加高速缓存的访问时间,进而可能导致性能降低。
解决高带宽的方案:
①解决高带宽需求同时不会明显增加高速缓存大小的做法是将不同的内容划分到不同的高速缓存中。 分立高速缓存的一个典型例子。
②不区分存储在分立高速缓存中的数据类型,而是将高速缓存按照不同的地址以交替的形式进行划分。这种组织形式被称为multi-banked高速缓存。
③改善高速缓存访问带宽的技术是流水线。
(6)高速缓存寻址和旁路转换缓冲
当代的微处理器系统都支持虚拟存储(virtual memory)。在虚拟存储系统中,程序(编译器)可以假设整个地址空间对其都是可用的,即便在实际情况下,物理存储比程序看到的地址空间要小很多,并且该物理存储可能被划分为多个块以供多个程序同时使用。系统通过两种类型的地址:虚拟地址(程序看到的地址)和物理地址(物理存储中的真实地址),营造了程序拥有较大地址空间的抽象。
缓存寻址的三种方式:
①一种是使用虚拟寻址,即通过虚拟地址的索引位进行缓存寻址,并将虚拟地址中的标签位保存在缓存的标签阵列中。
这种方式也被称作虚拟索引和虚拟加标签缓存。通过虚拟寻址,在访问高速缓存时不再需要物理地址,因此TLB和L1高速缓存的访问可以并行执行,访问TLB的延迟可以被完全隐藏。然而,这种方式的缺点是由于每个进程都拥有自己的页表,即使是相同的虚拟页地址,在不同进程内其到物理页地址的映射也不同。因此,虚拟寻址的高速缓存无法在多个进程(以多核系统、多线程或者时间片共享的方式)间共享数据。
②另一种方式是使用物理寻址,即通过物理地址的索引位进行高速缓存寻址,并将物理地址中的标签位保存在高速缓存的标签阵列中。
这种方式的缺点是在生成高速缓存寻址所需的物理地址时,需要访问TLB或者页表进行地址翻译,因此TLB的访问时间会直接累加到髙速缓存访问时间上。TLB通常被设计得容量较小,从而对其的访问可以在若干个处理器周期内完成。对TLB的访问时延与对L1高速缓存的访问延迟大致相等,因而将TLB的访问时延累加到L1高速缓存的访问时延,相当于将L1高速缓存的访问时延增加为两倍,这会显著降低性能。
③第三种方式是使用混合寻址,也被称为虚拟寻址和物理标签。
这种方式基于最重要的观察是页偏移位(用于在页内寻址一个特定的字节或者字位置)对于虚拟和物理地址都有效,因此这些位可以在访问TLB之前被使用。如果可以保证缓存索引位是这些位的一个子集,那么无论使用虚拟地址还是物理地址,缓存索引都是相同的。
一般的,最大高速缓存的大小需要满足以下公式:
(7)非阻塞式高速缓存
早期的高速缓存设计中,存储访问将会阻塞直到出现缓存缺失的请求访问到相应的数据为止,这样会出现性能比较低的问题。当代高速缓存体系结构通过引入一个被称为缓存缺失状态保持寄存器(Miss Status Handling Register, MSHR)的结构来解决上述问题。
5.3高速缓存性能
对于高速缓存层次的设计,处理器的性能取决于数据访问缓存命中(cache hit)和缓存缺失(cache miss)的次数。
缓存缺失的类型有很多种,通常可以用3C来表示:
①强制缺失(constraint miss):第一次将数据块读入高速缓存所产生的缺失,也被称为冷缺失(cold miss),因为当它们发生时高速缓存是冷的(空的)。
②冲突缺失(conflict miss):由于高速缓存相联度有限所导致的缺失。
③容量缺失(capacity miss): 由于高速缓存大小有限所导致的缺失。
缺失类型的区分:
区分强制缺失与其他类型的缺失比较容易。第一次对存储数据块的访问所导致的缺失是强制缺失,而其他缺失都不是。然而,区分冲突缺失和容量缺失并不总是很容易的。通常冲突缺失可以通过将相联度受限情况下高速缓存产生的缺失数--(减去)同样大小的高速缓存和数据块情况下全相联高速缓存产生的缺失数获得。除去强制缺失和冲突缺失,剩下的缓存缺失可以认为是容量缺失。
其他类型的缓存缺失:
① 一致性缺失:在共享存储多处理器系统中,为了保持高速缓存一致性而产生的缺失。
②系统相关缺失:由于系统活动如系统调用、中断和上下文切换而导致的缺失。当一个进程由于中断、系统调用或者上下文切换而暂停时,它的高速缓存状态会被干扰实体(另一个进程/线程或者操作系统)所扰乱。当进程恢复执行时,将会产生新的缓存缺失从而恢复被扰乱的缓存状态。这些缺失都是与系统相关的。
注:一致性缺失在多处理器系统中非常重要,它是并行程序产生可扩展性瓶颈的一个重要原因。
③上下文切换缺失:
又被分为两类--->a.替换缺失(replaced miss),发生在由于上下文切换扰乱缓存状态进而导致数据块被替换;重排序缺失(reordered miss),发生在缓存状态扰乱情况下数据块按照最近的位置在缓存中被重排序而不是被替换。
高速缓存的参数影响不同类型的缺失分析:
(1)高速缓存缺失的幂次定律(空间度量)
在单核/处理器系统中,应用的容量缺失率往往符合特定的趋势,被称为幂次定律(power law),其反映了串行程序高速缓存容量缺失受缓存大小影响的关系。
数学上讲,幂次定律表述了当针对基准高速缓存大小为C0、工作负载的缺失率为m0,对 于一个新的缓存大小C,其缺失率m可以表示为:
α表示工作负载对缓存大小变化的敏感度,α的范围为0.3-0.7,均值为0.5,当α取0.5时,
假设C=4C0,m=m0/2,对于一个普通的工作负载,为了将容量缺失率降低2倍,缓存大小必须增大4倍。因此,随着缓存大小不断增加,对缓存缺失率的减少是在不断减小的。
幕次定律的拟合度分析:
下图为应用缓存缺失率与单层缓存中缓存大小的关系,其缺失率归一化到缓存大小取最小值时
幂次定律的优缺点:
优点:
幂次定律在估算高速缓存性能时非常有用。
缺点:
①幂次定律可以适用的缓存大小范围是有限的。
当缓存大小足够大时,容量缺失将会下降为0而整体缺失数将会保持在一个稳定的值,然而幂次定律会错误预测整体缺失数仍然会不断下降。因此,幂次定律需要应用在正确的缓存大小区域内,避免进入容量缺失为0的区域。
②有些应用的缺失率展现出逐步线性的特点。
通常情况下这是因为应用内部有多个离散的循环,当缓存达到一定大小时,整个循环的工作集可以被缓存起来,这会导致缺失率有较大的下降。在这之后增加缓存大小不会带来明显的性能改善,一直到缓存大到可以容纳另一个循环的工作集。
(2)栈距离特性(时间度量)
幂次定律描述了应用缺失率受缓存大小影响的近似关系。研究人员可以表示一组应用的平均行为,甚至一些情况下可以是单个应用的行为。但是,存在一些情况使得幂次定律无法准确描述单个应用的行为。为了更好地描述应用缺失率行为受缓存大小的影响,研究人员利用了一种有效的特性信息,称为栈距离特性。
栈距离特性描述了在全相联或者组相联高速缓存中应用对缓存数据的时间重用行为。
为了获得在A路组相联且采用LRU替换算法的高速缓存上的栈距离特性,需要维护A+1个计数器:C1,C2,.....,CA,....。对于每一次高速缓存请求,将其中的一个计数器加1。如果高速缓存访问的数据块位于LRU栈的第i个位置,那么Ci加1。值得注意的是,栈中的第一个数据块是相应组中最近最常使用的数据块,而栈中最后一个数据块是相应组中最近最少使用的数据块。当出现缓存缺失时,数据块不在LRU栈中,这时将缺失计数器C(A+n)[最后一个]加1。栈距离特性可以通过编译器、模拟或者直接在有适当硬件支持的硬件上获得。
下图中展示的栈距离特性例子,越往右侧值越小:
通过栈距离特性,可以很容易计算出使用LRU替换算法的容量更小的缓存的缺失数。例如:对于具有相连度A`的更小的缓存,新的缓存缺失数可以计算如下:
(3)高速缓存性能指标
①平均访问时间(Average Access Time, AAT)
例题:
AAT的不足(了解即可,例子忽略):
①AAT 没有考虑ILP和MLP的影响。
②它不能够直接反映执行时间,而执行时间常常是最终的性能指标。
考虑到高速缓存性能对程序整体性能的影响,需要使用指令周期数(CPI)指标。
假设一个系统具有理想的存储层次,如L1高速缓存从来不会出现缓存缺失,并且访问时延为0。理想存储层次下的CPI被记为CPIideal。任何在其之上增加的指令周期数都是因为不完美的存储层次导致的,包括缓存访问时延和缓存缺失时延,以及访问速率和缺失速率。换句话讲,AAT是不完美CPI的主要贡献者。因此,如果指令中访问存储(加载或者存储)的比例为fmem的话,那么CPI可以用AAT表示如下:
CPI = CPIideal + fmem * AAT
③对于并行程序,由于不同线程的执行进度存在差异,高速缓存性能指标如缺失率与执行时间的关系并不直观。
5.4预取
当代的高速缓存设计通常都釆用了预取机制,即在程序访问数据之前将其读取到高速缓存中。预取减少了程序等待数据读取的时间进而提高了程序的运行速度。然而,由于预取是基于对未来处理器所需数据的预测,因此会消耗额外的存储带宽。此外,预测从来都不会完美,因此一些被预取的数据块可能永远不会被处理器使用。
通常有三个指标用于刻画预取机制的有效性:
①覆盖率coverage被定义为原始缓存缺失中被预取的比例,由于预取,缓存缺失变为缓存命中或者部分缓存命中。
②准确率accuracy被定义为预取数据中有效的比例,也就是导致缓存命中的比例。
③及时性timeliness描述了预取可以提前多久到达,进而决定了缓存缺失时延是否可以被完全隐藏。
如果预取的数据块被保存在特殊的存储中(如预取缓冲区),那么这三个指标(覆盖率、 准确率和及时性)是评价预取机制有效性的全部指标。然而,如果预取的数据块被直接放在高速缓存中,就会引发额外的问题,因而需要其他指标进行评价。例如,如果预取导致缓存块被替换并且由此导致缓存缺失,那么该预取就可能是有害的。但是如果预取本身导致缓存命中,那么就可以抵消上述缓存缺失的影响。因此,需要收集有效的、无效但是无害的、无效且有害的预取数三个指标才能更好地评价预取机制的有效性。
(1)步长预取和顺序预取
流缓冲区支持预取顺序访问。流缓冲区是一个先进先出(First In First Out, FIFO)的缓冲区,其中每一项包括一个缓存数据块的数据、该缓存数据块的地址(或标识)以及一个可用位。为了并行地对多个流进行预取,可以使用多个流缓冲区,每个缓冲区预取一个流。当有高速缓存访问时,则对高速缓存进行检查以确定是否匹配。如果请求的数据在高速缓存中,则不需要对流缓冲区进行任何操作。如果数据块不在高速缓存中,但是在流缓冲区的头部,则将数据移动到高速缓存中。流缓冲区中的下一个数据项变为头部并释放岀一个空闲位置,进而触发预取请求顺序读取缓冲区最后一个数据项地址的下一个地址的数据。如果数据块既不在高速缓存中,也不在流缓冲区中,则需要分配一个新的流缓冲区,后续的数据块会被预取到该流缓冲区。
①顺序预取(sequential prefetching)检测并预取对连续区域进行访问的数据。
②步长预取(stride prefetching)检测并预取连续访问之间相隔s个缓存数据块的数据,s是步长的大小。
实际上,流缓冲区无法有效处理任何非顺序的访问。包括非单位步长(s>1)的访问以及步长为负值(s= -1)的顺序访问。对于非单位步长的访问,由于访问地址只会与流缓冲区的头部数据项进行比较,因而每次访问将会导致流缓冲区不命中。为了解决这个问题,提出了两项技术以改进流缓冲区:分配过滤器和非单位步长检测机制。分配过滤器等待同一个流出现连续两次缺失后才分配一个新的流缓冲区,并且保证流缓冲区只分配给基于步长的访问。
(2)多处理器系统中的预取
在多处理器系统中,确保预取不会导致意外的性能负面影响比较困难。如果处理器预取数据块过早,那么在处理器有机会访问该数据块之前,可能会因为另一个处理器对该数据块的访问导致数据块无效。同时,被预取的数据块可能替换了更有用的数据块。因此,在多处理器系统中,必须保证数据块预取足够早,从而能够隐藏未来缓存缺失的时延,同时又不能太早,导致数据块被其他处理器先于预取处理器访问。
在单处理器环境中,由于缓存容量有限,过早预取可能会导致被预取的数据块替换更有用的数据块(如果高速缓存足够大,从而能够保留这两个数据块,则上述情况不会发生)。在多处理器系统中,即使高速缓存大到一定程度,过早预取也会导致从其他处理器中不必要地“窃取”缓存块,而这些缓存块很可能被再次“窃取”回去,进而损害性能。
5.5多核体系结构中的高速缓存设计
高速缓存体系结构中高速缓存的物理组成和逻辑组成:
①物理组成:指高速缓存如何组织到芯片上,即处理器核和高速缓存是否物理上直接相连。
如果高速缓存可以被所有处理器核直接访问,则称它为物理上集中的(physically united)。在某些情况下,高速缓存可能包含一个或者多个bank。只要所有的bank直接连接到所有的处理器核上,我们称这种高速缓存为集中式高速缓存(united cache)。然而,如果高速缓存物理上被划分为不同的块,而每一块被分配到一个处理器核上,并且该处理器核只与分配给它的高速缓存块直接相连,我们称这种高速缓存是物理上分布的(physically distributed)。每一块可能包含一个或者多个bank。"集中”和“分布”用于区分高速缓存的物理组成和逻辑组成。
②逻辑组成:指一个处理器核可以访问哪些高速缓存,如一个处理器核是否允许访问所有高速缓存,或者只是与该处理器核相连的那一部分高速缓存。
如果任何一个处理器核被允许访问所有高速缓存,那么这个高速缓存被称为是逻辑上共享的(logically shared)。 一个物理上分布的高速缓存可以被聚合起来形成一个逻辑上共享的高速缓存,如允许处理器核访问任何一部分的高速缓存,即使该部分的高速缓存并不与处理器核直接相连。如果只允许处理器核访问高速缓存的一部分,那么该高速缓存被称为逻辑上私有的 (logically private)。一个逻辑上私有的高速缓存可以通过只允许处理器核访问与其直接相连的高速缓存部分,进而构建在物理上分布的高速缓存之上。同时,一个逻辑上私有的高速缓存也可以通过将高速缓存划分为不同的分块,并且只允许处理器核访问特定的分块,进而构建在物理上集中的高速缓存之上。在讨论多核体系结构高速缓存组成的设计时,高速缓存物理和逻辑组成的区分对于避免歧义非常重要。
5.6高速缓存的物理结构
本小节主要将讨论为什么物理上集中的高速缓存对于设计小规模的多核处理器较为合适,但是由于将大量处理器核与高速缓存bank直接相连的开销较大,对于大规模的多核处理器则很难扩展。
(1)集中式高速缓存
下图展示如何使用多条总线在集中式高速缓存中实现交叉开关:
可以看出,交叉开关的复杂度随着处理器核数以及L2高速缓存bank数量的增加呈现平方式增长
多核体系结构的一个特性就是处理器核、高速缓存和互连相互竞争有限的芯片空间(关于这方面的定量分析)。 将交叉开关扩展到更多的处理器核上必然会减少实现处理器核和高速缓存的可用芯片空间。除了提供交叉开关的复杂度之外,由于形成高速缓存的物理连线(如字线、位线)的长度,一个大的集中式高速缓存往往访问时延较长。
整体上讲,大的集中式高速缓存的高访问时延以及互连大量处理器核和高速缓存bank的复杂性,限制了集中式高速缓存的可扩展性。这就导致了另一种物理组成分布式高速缓存的岀现。
(2)分布式高速缓存
由于物理上集中的高速缓存内在的不可扩展性,更多的多核体系结构不再采用集中式的体系结构。
一种便捷且符合逻辑的扩展多核系统的方式是将互连移动到存储层次的下层对高速缓存组成而言,多核体系结构更可能实现物理上分布的L2高速缓存,并通过互连网络将其连接起来,或者对接一个集中式L3高速缓存。
下图展示了采用环和2D网格互连的分片多核体系结构的例子。图中标示“R”的方块代表路由器。从这里开始,将L2髙速缓存中与处理器核相关联的区域称为高速缓存片(cache tile)。
(3)混合式高速缓存
很多种高速缓存的组成方式介于分布式高速缓存和集中式高速缓存之间,下图展示:让多个处理器核共享一个高速缓存,或者在L2层采用分布式高速缓存而在L3层釆用集中式高速缓存。
另一种设计是下图中展示的“分布式+集中式”的混合物理高速缓存组成。这种混合组成方式由于以下原因具有较好的应用效果。首先,物理共享只能存在于很少数量的处理器核之间。因此集中式高速缓存的设计相对比较简单。此外,因为高速缓存的数量比较少,连接它们所需的互联路由和链路也较少,进而数据互联传送的时延也较小。
下图展示了整体高速缓存访问时延随高速缓存大小的变化:
①一条曲线为访问延迟曲线,显示了访问一个集中式高速缓存所需的时间。当高速缓存变大时,由于高速缓存结构变大因而访问时间增加。
②另一个曲线为路由延迟曲线,展示了在互连网络上路由请求和响应所需的时间。
整体高速缓存访问时延为每个高速缓存访问时延和路由时延之和。
5.7高速缓存的逻辑组成
在多核配置中,如果L2高速缓存分布在与不同处理器核相关联的高速缓存片上,那么就存在多种逻辑组成形式:共享的、私有的和混合的。
如下所示,存在多种将高速缓存片聚合成逻辑共享高速缓存的方式:
这里需要考虑的一个重要的指标是数据与访问该数据的处理器核的相对距离,也被称为距离局部性(distance locality)。逻辑上共享设计的缺陷是对于大的多核系统,其距离局部性较差。
①一路片相连
如果处理器核0访问数据块,并且该块被映射到高速缓存片15,则网络的距离(假设是二维网格)是6跳。为了收到一个消息,每个路由节点根据其内部实现的流水线段数,可能需要引入至少3个时钟周期的延迟。传输时间取决于链路带宽,对于每个数据块大概需要1-2个时钟周期。因此,6跳的网络距离需要引入至少6x3+1 = 19个额外的时钟周期(假设是直通路由),并且如果路由延迟是5个时钟周期的话,那么引入的额外开销为6x5+2 = 32个时钟周期。即便是路由延迟为3个时钟周期,当网络运行在处理器核最高频率一半的情况下,最坏的往返时延为2x2x19 = 76个时钟周期。因此,对于一个采用了逻辑共享高速缓存且规模较大的多核系统,其访问远端高速缓存开销巨大。
②二片相连
任何一个处理器核可以在最多3跳的网络延迟内访问任何高速缓存片组内至少一个高速缓存片,相对于一片相联设计中最坏情况下需要6跳的网络延迟的情况,高速缓存访问的性能得到了极大的提升。
③全片相连
如果将高速缓存片组织成片组(全片相联)的方式更加集中而不是随机的话,那么性能提升的程度就会减少。可以设想将ID连续的高速缓存片组织到同一组内,如片0和1分到同一组,片2和3分到同一组,以此类推。如果釆用这种分组方式,最坏情况下一个处理器核到片组的距离高达5跳的网络延迟。
相联度越高,定位数据块时需要检查的片就越多。这就需要消耗额外的功耗,并且相对一片相联的设计会产生较高的网络流量。通过要求处理器核首先检查片组中靠近该处理器核的片,并且只有在较近片中不包含访问数据块的情况下查询较远的高速缓存片措施,这些缺陷可以得到一定程度的缓解。除此之外,即便具有较高的片相联度或者铺开式的片组织方式,对于有多个线程访问同一个数据的并行程序,特别是数据放置在离一些线程较远的高速缓存片上时,仍然很难达到较好的距离局部性。在这种情况下,较好的距离局部性只能通过复制数据块获得。
如下图所示,也可以采用私有和共享高速缓存混合的组织方式。在图中片被划分为不同的组,每一组包含逻辑上共享的四个高速缓存片。然而,每一组都是私有的,组之间保持着缓存一致性。在保持一致性的情况下,数据块可以在不同的片组之间复制。然而在一个组内,只可能存在一个数据块副本。
下图,通过可视化方式展示了在多核体系结构中不同逻辑高速缓存组织方式的差异:私有的、共享的、片相联共享的和混合的。x轴为距离局部性,描述了处理器与所访问数据的物理距离。y轴为容量和碎片,描述了可用聚集容量的大小(容量)和可以被单个处理器核访问的聚集容量大小(碎片)。
两个极端例子:
①私有高速缓存结构
每个处理器只能访问一个高速缓存片(最坏碎片)。如果运行在处理器核上的应用的工作集超过了本地高速缓存片的大小,应用将会产生大量的容量缺失。同时,也可能有其他原因导致缓存容量过剩,如没有线程运行或者有线程运行但是工作集很小。这些过剩的缓存容量无法共享给其他处理器核,因此导致最坏碎片。更进一步,数据可以被复制到不同的分片上,这就意味着由于数据副本会占用高速缓存空间,导致可以存储不同数据的聚集容量减少。在这种方式下,数据总是保存在与处理器直接相连的本地高速缓存片上,因而具有最好的距离局部性。
②共享高速缓存结构
这种方式下高速缓存碎片最少,因为每个处理器可以访问整个聚合缓存容量。同时,这种方式由于不需要复制数据,因此也拥有最好的聚合容量。然而,由于数据分散在多个高速缓存片上,这就意味着从平均概率的角度来看,数据离每个处理器核都比较远,因此距离局部性最差。
改善技术:
①牺牲品复制 victim replication
该技术通过将映射到远端高速缓存片的数据复制到本地高速缓存片,可以改善共享高速缓存组成方式的距离局部性。具体来讲,从内层高速缓存替换出的数据块(牺牲品)可以被临时缓存在本地高速缓存片中。这种复制方式虽然减少了聚合缓存容量,却改善了距离局部性。此外,这种技术也引入需要被解决的缓存一致性新问题。
②容量共享 capacity sharing
该技术将从本地高速缓存片替换岀的数据块复制到远端高速缓存片上。之后,如果处理器再次请求该数据块,则可以在远端高速缓存片中找到而不需要从外层高速缓存中读取该数据块。容量共享技术以牺牲距离局部性为代价,减少了高速缓存碎片。
(1)散列函数
在共享高速缓存的组织方式下,散列函数负责将数据块映射到高速缓存、高速缓存片或者片组上。散列函数需要简单,并且易于生成,同时不会出现数据块到片的不均衡映射。 简单的散列函数只是交错地将数据块或者页地址映射到不同的高速缓存片上,这种散列函数会产生一些低效行为,如一些组被使用而另一些组不会被使用,因此在现实中并不实用。
(2)改善共享高速缓存的距离局部性
共享高速缓存距离局部性较差的原因:
①对于共享高速缓存而言,局部性较差是无法复制数据块导致的。
如果将数据块映射到距离处理器核较远的高速缓存片上,那么在每次数据块缺失时处理器就必须从远端高速缓存片中读取该数据块。如果允许处理器核复制数据块到本地高速缓存片,那么距离局部性可以得到显著的改善。
②通过复制数据改善距离局部性的一种方式是牺牲品复制。
数据复制产生的问题及措施:
①数据复制会引入数据一致性问题,因此需要相应的机制以保证可以正确处理。为了保证复制数据的一致性,需要通过一致性协议在高速缓存中的数据块发生变化时,通知其他持有该数据块副本的缓存。
②数据复制引入的另一个问题是如何管理L2高速缓存的使用,从而更有效地放置本地数据块和数据副本。
数据复制的缺点:
①高速缓存的缺点是牺牲品数据块和普通数据块会竞争L2缓存容量,这种容量竞争可能会导致本地L2缓存容量缺失率增加。
数据复制的新方法:
① 选择性复制的一个代表性研究工作是自适应选择性复制。
该研究发现在商业工作负载中有一类数据被大量线程共享,但是该类型数据大部分情况下为只读数据。这些只读数据虽然只占用很小的缓存容量,但是会造成大量的缓存缺失。因此,相对于共享读写数据块,这些共享只读数据块更适合作为数据块复制的对象。
②针对共享高速缓存组织方式的复制技术可以吸收私有高速缓存组织方式下的一些优势,如较好距离局部性。
(3)私有高速缓存结构中的容量共享
私有高速缓存组织方式下的主要缺陷:由于缺乏容量共享而导致的缓存容量碎片。
缺乏容量共享在多核系统中会导致严重的系统性能下降,特别是当一组差异较大的串行程序运行在不同的处理器核上时。
这种不均衡的高速缓存利用率会导致整体性能的严重下降,这是由于需要更大缓存容量的程序无法使用相邻高速缓存片上空闲的缓存容量。如果没有容量共享,这些多余的缓存容量无法被其他需要更多缓存容量的处理器核使用。
解决方法:
①缓存共享机制
如:协调缓存 CC,动态溢出接收 DSR
在数据块没有被复制的情况下,CC允许每个处理器核将替换出的数据块保存在其他任何一个片上私有高速缓存中。
DSR通过将应用进行分类尝试解决上述缺陷:一类应用可以通过超过本地L2高速缓存的额外缓存容量获得性能提升,另一类应用的性能则对L2高速缓存容量的减少并不敏感。
CC和DSR都允许将远端高速缓存当作本地缓存的牺牲品缓存,这样做可以减少片外的缓存缺失数量。然而,如果考虑远端缓存的命中次数,这种管理容量共享的策略是否是最佳?
答案是并不一定。将远端高速缓存作为一个大的牺牲品缓存之所以可以取得性能提升基于一个重要假设,即被替换出的数据块相对于当前存储在本地高速缓存的数据块而言,被处理器核重用的概率要小很多。然而,这个假设并不总是成立的,特别是对于溢出者应用,这个假设大部分时候都不成立。这是由于溢出者应用往往存在一个常见的行为特征,即最近最少使用的数据块更有可能在未来被访问。换句话讲,溢岀者应用通常表现出反LRU的行为特征。
课堂习题
习题1
习题2
四路相连--->想象为4个格子的栈
建议阅读:
并行多核体系结构基础——第五章的伪LRU(PLRU)算法简要介绍
阅读过后顺一遍思路必定秒懂。
LRU-替换最近最久未被访问的元素
MRU-替换前一个被访问过的元素
FIFO-先进先出
OPT-替换后置位最久会被访问到的元素
PLRU-运用二叉树处理
习题3
习题4
LRU-替换最近最久未被访问的元素
课后习题
习题1
(a)
AAT1=T1+M1 * T2+M1 * M2 * TM = 1+0.2 * 9+0.2 * 0.1 * 100 = 4.8
(b)
AAT2=T1+M1 * T2+M1 * M2 * TM = 1+0.2 * 12+0.2 * X * 100 = 3.4+20X <AAT1=4.8
解得:X<0.07 ,故L2缺失率至少降低3%才能减少AAT
(c)
M2 = 0.1 * (√2/2) = 0.0707
故此时L2新的缺失率为0.0707
新的AAT3 = 1+0.2 * 12+0.2 * 0.0707 * 100 = 4.814 ≈ AAT1
所以,新的L2增加了AAT,但增加幅度不大,几乎可以忽略不计。增加L2容量可以降低缓存缺少,但是会引起访问时延的增加,因此我们做缓存设计的时候需要兼顾二者,取最优解。
习题2
有4个缓存行,答案如下:
LRU-替换最近最久未被访问的元素
较为简单,根据本话理解推算即可。
FIFO-先进先出
较为简单,根据本话理解推算即可。
OPT(Belady最优)-替换后置位最久会被访问到的元素
思路绕,要寻找最久会被访问的元素,但根据本话理解推算即可。
PLRU-运用二叉树处理
不好理解,这里作图:
习题3
(a)
(b)
习题4
α = 0.3 ,0.5m0=m0 * (c/c0) -α ,C = 10C0 增加了10倍
α = 0.5,0.5m0=m0 * (c/c0) -α , C = 4C0 增加了4倍
α = 0.7,0.5m0=m0 * (c/c0) -α , C = 2.7C0 增加了2.7倍
α = 0.9,0.5m0=m0 * (c/c0) -α , C = 2.16C0 增加了2.16倍
习题5
第一步,由幂次定律,计算每个组数的缺失率
m=m0 * (c/c0) -α
其中,m0=10%,已知有8路,如果组数=1,C1=1/8 C0;组数=2,C2=2/8 C0;
以此类推(高速缓存的大小=组数 * 路数 * 缓存块的大小)
m1=2√2 m0=0.28
m2=2m0=0.2
m3=0.16
m4=0.14
m5=0.13
m6=0.12
m7=0.11
m8=0.1
第二步,由栈距离特性
C>A=0.1
A`=1,m1=0.28=0.1+C2+...+C8
A`=2,m2=0.2=0.1+C3+...+C8
A`=3,m3=0.16=0.1+C4+...+C8
A`=4,m4=0.14=0.1+C5+...+C8
A`=5,m5=0.13=0.1+C6+...+C8
A`=6,m6=0.12=0.1+C7+...+C8
A`=7,m7=0.11=0.1+C8
所以,
C8=0.01
C7=0.01
C6=0.01
C5=0.01
C4=0.02
C3=0.04
C2=0.08
C1=0.9-C2-C3-...-C8=0.72
由于计算量过大,α=0.3和0.8计算方法同上,故略
习题6
解析题目:
栈1和2--->3个时钟周期
栈3和4--->6个时钟周期
栈5和6--->9个时钟周期
栈7和8和9--->12个时钟周期
(a)
应用1:
(60% + 10% )× 3 +( 5% + 3%) × 6 +( 2% + 0%) × 9 + (8% + 7% + 5% )× 12 = 5.16
(b)
应用2:
(50% + 10%) × 3 + (8% + 7%) × 6 + (5% + 1%) × 9 +( 1% + 1% + 17%) × 12 = 5.5