Intel, AMD及VIA CPU的微架构(7)

来源:互联网 发布:网络设备连接软件 编辑:程序博客网 时间:2024/06/04 18:27

3.11.      AMD K8与K10中的分支预测

BTB结构

K8与K10 AMD处理器的分支预测机制与代码缓存相关。1级代码缓存有1024行,每行4*16字节,2路组相联。

在代码缓存中每个16字节块具有分支标志(indicator)的一个关联集。有9个分支标志,与代码块的字节序0,1, 3, 5, 7, 9, 11, 13及15相联。大多数分支指令长度是两字节或更长。两字节或更长的分支指令将具有至少一个分支标志,即使仅有用于奇数地址与地址0的标志。在字节0处的额外标志覆盖分支指令跨过16字节边界,在字节0处结束的情形。

每个分支标志有两个比特信息来涵盖以下情形:(0)没有分支或永不跳转,(1)使用分支选择子1,(2)使用分支选择子2,(3)使用分支选择子3。除了9个分支标志,还有3个分支选择子。每个分支选择子有分支目标缓冲内的索引,以及局部分支预测信息。局部分支预测信息可以是“永不跳转”,“总是跳转”,“使用动态预测”,或“使用返回栈缓冲”。还有一个标志表示分支是否是一个调用。这用于在返回地址栈上压入一个返回地址(参考第28页)。

分支目标地址被保存在有2048项的分支目标缓存(BTB)中。返回地址被保存在返回地址栈中,它在K8中有12项,在K10中有24项。

分支预测机制工作如下:永不采用的分支得不到分支标志、分支选择子及BTB项。分支第一次被采用时,它得到一个设置为“总是跳转”的分支选择子,以及一个表示目标地址的BTB项。如果该分支随后没有被采用,那么该分支选择子被改变为“使用动态预测”。它从来不会从“使用动态预测”回到“总是跳转”或“从不跳转”。动态预测机制描述如下。预测器比特可以表示至少以下值:“不跳转”,“总是跳转”,“使用动态预测器”,“使用返回栈缓冲”。K10还有间接跳转的预测器。

某些文档称,在返回栈缓冲耗尽时,返回指令占据一个分支目标项,但实验看起来显示在返回栈缓冲耗尽时,返回总是被误预测。

在被从1级缓存逐出时,分支选择子及部分局部分支预测信息被拷贝到2级缓存。因为缺乏空间,BTB的索引不拷贝到2级缓存。在缺少BTB项或由于逐出到2级缓存BTB索引丢失的情形下,有一个分支目标地址计算器可以计算直接跳转与调用的目标地址。根据我的测量,丢失的分支目标地址的计算要额外4个时钟周期,要小于完全误预测的代价。这使得条件及无条件跳转与调用可以被正确预测,即使它们已经被从BTB及/或1级缓存逐出。当然,分支地址计算器不能计算间接跳转与返回的地址。如果已经被从1级缓存中逐出,即使仍然在返回栈缓冲中,返回还是被误预测。

这个设计的一个缺点是,对每个对齐的16字节代码块,不能有超过3个控制转移指令,除了从不采用的分支。如果在同一个16字节代码块中有超过3个采用的分支,它们将持续从彼此偷取分支选择子与BTB项,导致每次执行两个误预测。因此,避免在一个对齐的16字节代码块中超过3个跳转、分支、调用及返回是重要的。从不采用的分支不计在内。三个分支的限制很容易超出,如果例如一个swtich/case语句被实现为一系列dec/ jz指令。

另一个问题是该设计对每两个字节代码仅允许一个控制转移指令。大多数控制转移指令使用多个字节的代码,但返回指令可以被编码为单字节指令。这会导致两种问题。如果两个分支共享相同的分支选择子,发生第一种问题。如果一条分支指令在一个偶数地址结束,在随后的奇数地址处跟有一条单字节返回指令,这两条指令将共享分支选择子,因此在大多数时间将被误预测。

第二种问题与没有分支选择子的单字节返回指令相关。当存在对一个单字节返回指令的直接跳转,或者一条单字节返回指令直接跟在一条误预测分支后时,这会发生。如果单字节返回指令在一个不能被16整除的偶数地址上,在这些情形下,分支选择子不会被载入,返回被误预测。

第一种问题可以通过在偶数地址放置单字节返回指令来避免,第二种问题可以把它放置在奇数地址(或者被16整除的地址)。这两种问题可以通过使得返回指令长于1个字节来避免。可以在返回指令前插入一个段前缀或F3前缀,使它两字节长,或者使用一个0偏移参数编码返回指令,使之三字节长。如果前接的是一个条件跳转,或存在到它的直接跳转,建议使得返回指令超过1字节。一个返回前接的调用指令应该被一个跳转替代。

误预测惩罚

AMD手册称,如果代码段基址是0,分支误预测惩罚是10个时钟周期,如果基址非0,是12个时钟周期。在我的测量中,我发现最小的分支误预测惩罚分别是12与13个时钟周期。在大多数32位操作系统及所有的64位系统中代码段基址是0。在16位系统中几乎总是非零(参考第165页)。

误预测惩罚对应流水线长度。远程跳转、调用及返回不被预测。

条件跳转的模式识别

AMD使用帶有如第8頁所解釋的全局8或12比特歷史的雙層自适应预测器。简单的重复模式与重复次数最多9或13的小循环可以被这个机制预测。第8页的规则显示看哪些重复分支模式可以被完美预测。

AMD优化指引显示全局模式历史表有16K项。这个表由全局历史的8或12个比特结合部分分支地址索引。我在K8上的测试显示它由一个8比特历史以及分支指令最后字节地址的序号4-9比特索引。这形成16K项,如果没有比特合并。某些比特彼此间以及/或者与部分分支目标地址XOR,是可能的。

总是重蹈旧路的分支不会污染全局分支历史寄存器。这由保存在分支选择子块的信息来完成。一个分支被假定为不采用,直到它第一次被采用。在一个分支第一次被采用后,它被假定为总是采用,直到下一次它不被采用。在一个分支已经被采用,然后不采用之后,它被标记为需要动态预测。然后使用带有8比特全局历史的双层自适应算法预测它。

这个机制使得预测重复次数最多9或13的循环成为可能,即使它们包含分支,只要这些分支总是重蹈旧路。

我在K8上的测试显示动态分支预测,比从上面描述设计所预期的失败次数要多得多,模式学习时间可以相当长。对此我无法解释,但可能是分支模式历史表比显示的要小,或者基址比这里描述的更复杂。

间接分支的预测

对间接跳转与间接调用,K10有一个有512项的独立的目标缓冲。双向分支(two-waybranch)可能共享12比特历史计数器。具有多个目标的间接跳转可以被预测,如果它们遵循一个规则的模式。更早期处理器预测间接跳转总是重蹈旧路,如下描述。

返回栈缓冲

在K8中返回栈缓冲有12项,在K10中有24项。这超出普通应用所需,除了递归过程。返回栈缓冲的一个解释,参考第25页。

文献:

分支预测机制在以下文档中描述,尽管这些可能不准确:

AMD Software Optimization Guidefor AMD64 Processors, 2005, 2008.

Hans de Vries: Understandingthe detailed Architecture of AMD's 64 bit Core, Chip Architect, Sept. 21, 2003.www.chip-architect.com.

Andreas Kaiser: K7 BranchPrediction, 1999. ww.agner.org/optimize/KaiserK7BranchPrediction.pdf.

Talk at Stanford 2004 stanford-online.stanford.edu/courses/ee380/040107-ee380-100.asx.

3.12.      AMD Bulldozer,Piledriver与Steamroller中的分支预测

AMD Bulldozer有一个不与代码缓存关联的,新设计的分支预测设计,不像之前的型号。预测机制被描述为局部预测器与全局预测器的一个混合。最可能,分支预测器基于感知器。感知器类似于神经元,它通过追踪分支历史中的相关来学习。不像自适应双层预测器,感知预测器可以学习非常长的分支模式。

根据AMD的软件优化指引,分支目标缓冲(BTB)有两层。1级BTB被组织为4路128组 = 512项的组相联缓存。在Bulldozer与Piledriver中,2级BTB有5路1024组 = 5120项,在Steamroller中可能是10240项。

一个计算单元的两个核之间BTB与预测器是共享的。

我的测试显示,在一定的学习时期后,复杂的重复模式可以被良好预测。看起来对可以预测的分支模式长度没有严格的界限,即使非常长的模式也可以预测。看起来没有循环计数器,嵌套循环不能良好预测。间接分支预测良好。在Steamroller中预测成功率高于之前的型号。

误预测惩罚

误预测惩罚被声明为,对条件及间接分支最少20个时钟周期,对无条件跳转与返回,15个时钟周期。我的测量显示对条件分支最多19个时钟周期,对返回最多22个时钟周期。

返回栈缓冲

返回栈缓冲有24项。

文献:

Software Optimization Guide forAMD Family 15h Processors. AMD, January 2012.

Daniel A. Jiménez, and CalvinLin. "Dynamic branch prediction with perceptrons." The SeventhInternational Symposium on High-Performance Computer Architecture, 2001., pp.197-206. IEEE, 2001.

3.13.      AMD Ryzen中的分支预测

Ryzen中的分支预测基于感知器。我的测试显示重复次数最多12的循环可以被预测得非常好。更多重复次数的循环,在最后一次迭代后,有时有一次误预测,有时没有。嵌套循环与循环内分支预测良好。重复模式预测良好,对周期长度没有明显限制。间接跳转或调用形式的多路(multiway)分支也被预测,虽然不如条件跳转那么高效。

分支信息不再附加到代码缓存,在同一个代码缓存行有许多分支,不是严重的问题。

分支目标缓冲(BTB)与历史缓冲大小未知。AMD文档称每个BTB项包含两个分支。

误预测惩罚测量为大约18个时钟周期。

返回栈缓冲有32项。

文献:

Mike Clark: "AMD and thenew “Zen” High Performance x86 Core". Hot Chips Symposium, California.August 23, 2016.

3.14.      AMD Bobcat与Jaguar中的分支预测

BTB结构

跳转与分支的位置保存在两个数组中,根据下面引用的论文,一个“稀疏分支标记数组”,对每个64字节缓存行,它可以保存2个分支,以及“稠密分支标记数组”,对每8字节代码,它可以保存2个分支。在我的测试中,Bobcat可以在2级缓存中每64字节代码预测2个分支,这表示稀疏分支数组,但不是稠密分支数组,耦合到这两层缓存。如果这两个数组都使用了,我们可以预期1级缓存每64字节最多18个分支。在我的测试中,Bocat与Jaguar能够预测1级缓存每行16或17个分支,依赖于分支的位置,但不是18。

当分支数超出时,有许多误预测,因为分支持续从数组将彼此逐出。

从不采用的分支被包含在分支标记数组中。

误预测惩罚

下面引用的论文显示13个时钟周期的误预测惩罚。不过在我的测试中,误预测惩罚范围从8到19个时钟周期,依赖于后续指令。就这方面来说,整数与浮点代码间没有一致的差异。

条件跳转的模式识别

分支预测器行为近似于带有26比特历史(参考第8页)的双层自适应分支预测器,或稍好。没有专门的循环预测器。这意味着带有许多分支或嵌套其他循环的循环预测不佳。我没有模式历史表大小的信息,但我们可以确定它小于226

总是采用的分支被包含在历史缓冲中,而从不采用的无条件跳转与分支不会。

间接分支的预测

处理器可以预测2个以上不同目标的间接跳转,但误预测频繁。

返回栈缓冲

根据我的测量,在Bobcat上返回栈缓冲有12项,在Jaguar上是16项。

文献:

Brad Burgess, et. al.: Bobcat:AMD's Low-Power x86 Processor. IEEE Micro, March/April 2011, pp. 16-25.

阅读全文
0 0