Skip to content

方法Method

gshare全局历史分支预测

Gshare branch prediction · Global history with index sharing · gshare预测器

将全局方向历史与分支地址异或索引,保存查询时上下文并展示历史能区分情境也会制造碰撞。

形式陈述 ​

双态预测按PC选一个二位计数器;同一PC总去同一槽,无法区分“这一次前面发生了什么”。gshare保留一段全局方向历史,并把它与PC一起用于选择计数器。计数器如何输出N/T、如何饱和训练不变,变化的是上下文到槽的映射。

延用32位四字节对齐PC、串行正确路径反馈协议和T=1、N=0。表有 2m 个槽,0≤h≤m≤30,每槽初态默认1。全局历史寄存器 H 有 h 位,初值零,最低位表示最近一次实际方向。本文把不足 m 位的历史放在索引高端,定义

a=(PC>>2)mod2m,j=a⊕(H≪(m−h)),y^=1[C[j]≥2].

两项都小于 2m,异或后的 j 也在表内。h=m 是PC低 m 位与同宽历史直接异或;h=0 时 H=0,无须读取历史比特,索引退化为 a。采用低端对齐、折叠更长历史或其他hash是别的具体变体,比较数字时不能暗中切换。

predict(pc)必须保存当时的 H、j 和建议。真实 y 揭示后,先对保存的 j 按二位规则加一或减一并饱和,再更新

H←((H≪1)|y)mod2h.

h=0 时模1结果恒为零。这里的“全局”指trace中所有条件分支共同推进同一个 H,不是每个PC各有一份历史;不把未出现的无条件跳转、错误路径分支或中断偷偷加入序列。参考器限定 m≤12 以限制内存。

历史不变量可直接归纳:在第 t 次反馈后,H 是已揭示方向 y0…yt−1 的末 h 位,不足时在左侧补零。初始为空前缀成立;左移把旧末位序列向高位送一格,或入 yt,模 2h 丢弃最老的一位,恰得到下一前缀的后缀。由此,当前预测只依赖过去反馈与当前PC。更新计数器的索引仍属于旧前缀,不属于刚加入当前答案后的新前缀。

直觉

想象同一条条件判断在两种上下文中表现相反。把所有情况混在一个计数器里,证据会互相抵消;如果最近几次分支能说明现在是哪一种情况,就可以给不同情境各留一份偏好。

这里保存的是方向序列,不是所有先前PC,也不是程序变量。两个执行前缀可能有相同方向后缀而经过完全不同的代码;相同后缀也可能不足以决定下一结果。历史只是一个有限特征,不带“世界从此可预测”的保证。

旧历史索引与反馈次序

异或也不是无冲突编码。固定某个 H 时,a↦a⊕(H≪(m−h)) 是索引集合的一个置换;因此它不会在同一历史下把两个不同的 a 合并。但是不同历史间可以碰撞:当

a⊕a′=(H⊕H′)≪(m−h),

两个PC/历史组合就访问同一槽。左边与右边的差异可能恰好抵消。把两份信息混合进 m 位输出,并没有得到 2m 位的唯一身份。

例子与边界

一个历史位足以学会交替 ​

只运行PC=0x100,真实方向为 (TN)^8。取 m=h=1,两个计数器初态都是1,H=0。前四次可以逐项复算:

次数 旧H 查询槽 旧计数 建议 实际 新计数 新H
1 0 0 1 N T 2 1
2 1 1 1 N N 0 0
3 0 0 2 T T 3 1
4 1 1 0 N N 0 0

此后两个槽分别稳定支持T和N,16次只错第1次。同初值的bimodal把两种上下文合在一起,16次全错。这个例子说明了为何历史可能有用;它没有证明gshare在所有序列上优于bimodal。

若把 m,h 同时增至2,冷启动还出现历史00、01、10等不同情境,16次会错2次。更多状态可能要更多热身,即使最终规律可预测,也不应只以状态数断言有限trace成绩更好。

相关分支与过长历史的反例 ​

现在每轮依次执行A=0x100、B=0x108,B的方向复制本轮A;A按 N,T,N,T,… 交替。16轮共32次,实际方向序列为 (NNTT)^8。bimodal的四槽能分开两个PC,却没有区分轮次,总共错16次。

取 m=2,h=1,短历史放在高位:A的地址索引0,B的地址索引2。B在刚见N时访问 2⊕0=2,刚见T时访问 2⊕2=0。稳定后,槽2收到的都是N,槽0收到的都是T;最初两次T各错一次,总共2错。

保留四槽、把历史改为 h=2 却会恶化到23错。稳定周期里,A的T在旧历史00时访问槽0,B的N在旧历史10时也访问 2⊕2=0;B的T在01时访问槽3,随后A的N在11时也访问槽3。历史区分出的情境被hash重新合并成相反证据。槽0在0与1附近来回,槽3在1与2之间来回;每四次会错三次。初始短前缀略有不同,完整32次因此是23而非24。

这不是“历史太长必然不好”的定理,而是一个可执行的非单调见证。把表改为八槽时,h=2 又只错2次,h=3则错23次。讨论历史长度必须同时给地址取位、对齐方式、表容量、初态与实际trace。

先移动历史再寻槽,会教错对象 ​

回到一位历史交替例子。第一次查询旧 H=0 的槽0,建议N但真实为T,应把槽0从1训练到2。若先把历史改成1,再重新算索引,更新的却是槽1;第二次来到真正的旧历史1,槽1已经被错误教成T,又恰好与实际N相反。

这个错误变体在16次交替上全部猜错,合法实现只错1次。保留ticket不是装饰性的日志,而是在接口中保存“这次建议来自哪里”。当前串行协议下保存索引已足够;若允许多个未决分支,history检查点、更新顺序和错误路径撤销都要另定,不能声称一个保存整数的ticket已经完成推测恢复。

推论与应用

在 h=0、表大小与初值相同的条件下,gshare与bimodal对任何合法trace的建议、计数表和错误位置逐步相同。证明同时归纳:初表相等;本轮历史恒零,所以查询同一槽、给同一建议;反馈对同一旧值做同一转移,下一表仍相等。这是参数限制后的等价,不应把两个一般机制无条件标成同义词。

计数表加历史共 2⋅2m+h 个逻辑状态比特。固定32位字模型中索引、预测、反馈各用 O(1) 字操作,初始化仍是 Θ(2m)。真实硬件是否能在要求的一个取指周期内完成异或、表读和输出,要看电路和端口,常数次软件操作不能证明其时钟延迟。参考器的整表快照、独立oracle和逐事件JSON另有容量相关成本。

多在途预测状态恢复另行扩展本页的逐次反馈合同:查询立即把预测位移入推测历史,任意存活记录可先解析,错误时恢复前检查点并取消年轻后缀。方向表仍等按序提交才训练,使用保存的查询索引和提交时当前计数器;已提交历史副本用于整体flush。

如果历史对某些PC有帮助、对另一些PC造成干扰,可以同时保留地址偏好与历史偏好,再用锦标赛式选择器根据过去的相对正确情况挑一方。多保留两张表的费用也必须计入,不能把组合器的全部存储当成单个分量的预算。

终点任务要求重现2错与23错的同容量差别,并找出至少一对相撞的PC/旧history。若只输出最终准确率而没有保存查询索引,就很难区分“规律本身难学”和“训练错了槽”。它还要求比较先热身再计分与冷启动,且不把这份trace实验冒充带BTB和flush的完整CPU模拟。

参考资料
  • Scott McFarling,Combining Branch Predictors,DEC WRL TN-36,1993,§§5、7,尤其“Global History with Index Sharing”:全局历史与PC异或,短历史置高位及容量干扰。
  • Tse-Yu Yeh and Yale N. Patt,Two-Level Adaptive Training Branch Prediction,MICRO 1991,§2.1:先由旧历史查询模式表,反馈更新所查条目并移动历史。原文该节的per-address历史与本页单一global寄存器不同,引用的是更新接口,而非把两种组织混为一谈。
关系图谱3 个相邻概念 · 1 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组