Skip to content

算法Algorithm

Store Set 内存依赖预测

Store-set memory dependence prediction · Store sets predictor · Store Set依赖预测

从历史冲突合并访存PC集合,用同集合store链和最近未完成store表生成等待边,同时保留独立违例检测与恢复。

同一条load每次都越过同一条慢store,然后每次都重放,机器其实已经有了可用经验:这对指令经常访问相同位置。Store Set把这种历史变成调度建议,让load下次先等一等。它预测的是“应该等谁”,不是“内存里是什么值”。

形式陈述 ​

两张表连接静态PC与动态实例 ​

本页以违例检测和后缀重放作为始终保留的安全底座。训练输入是实际发现的store/load冲突PC对;调度输入则是按年龄排列的动态访存项。一个PC可以有许多动态实例,PC集合与某次在途store身份必须分开保存。

参考器采用两张表:

  • SSIT:访存PC→集合号;没有条目表示尚无历史
  • LFST:集合号→本窗口中最近的未完成store年龄;没有条目表示当前不必等该集合的store

SSIT是跨窗口保留的预测历史,LFST是当前执行的状态。一个预测器对象只能由一个活动窗口管理;下一次调用可以接着用它学习过的SSIT,但不会沿用上次已经结束的动态store身份。

本页是精确PC键、立即完整合并的教学实现。 原论文§6的SSIT是无tag有限索引表,冲突集合采用局部改写逐步合并;本文用Python字典保存完整PC,并在冲突时一次改完整个集合。两者共享两级查找与store链思想,存储费用、合并速度和别名行为却不同。[1]

冲突怎样更新集合 ​

设冲突store与load的PC为p、q,SSIT中的集合号为A、B:

原有信息 更新
两者都无集合 分配新集合号,同时赋给p、q
只有一方有集合 另一方加入该集合
两者已有相同集合 保持
两者属于不同集合 选较小号为赢家,把输家集合的全部PC改到赢家

新集合号从0递增,清表时才归零。不只改冲突的一个PC:例如集合0有A、X,集合1有B、Y,新发现A与Y冲突,就把A、X、B、Y全部归到0。本页完整合并维护一份真正的PC等价类划分,但不声称同类成员每次都访问同一个内存位置。

一条等待边为什么能代表许多store ​

在初始入窗、冲突合并后的恢复、或显式清历史后,按程序年龄扫描当前未退休项,重新建立等待链:

  1. 清空LFST及各项旧预测前驱;已经DONE的项无需新增等待
  2. 未完成load若有集合号,记下LFST中该集合的当前store作为预测前驱
  3. 未完成store若有集合号,也先记同样的前驱,再把LFST改成自己

没有集合或LFST为空就不加边。地址和数据仍可独立提前计算;但store只有地址/数据到齐且预测前驱已DONE,才能标为完成,load也要等预测前驱完成后才做真实来源查询。这里“store完成”只表示其字段可靠地准备好,不是退休或写内存。

store完成时,仅当LFST还指向自己,才删除该条目。如果LFST已经指向更年轻store,不能把它一起清掉。这样后续消费者不会因为较老store完成而漏掉仍待完成的年轻store。

直觉

让store先排成一条链 ​

集合里有三条在途store S0、S2、S5。如果让load分别等三者,需要三个等待来源。本协议先约束S2等S0、S5等S2,再让load只等S5。等到S5完成时,前面那条链也已经完成了。

这条链可能比真实依赖更保守。load实际只读S0的位置,但集合中碰巧还有无关的S5,它仍会等S5。预测器用较简单的等待表示,交换了部分调度自由。是否划算要看省下多少重放、增加多少等待,不能只统计“训练后没有错”。

静态集合相同,动态等待身份仍逐项更新
例子与边界

冷启动、热身与地址模式变化 ​

继续使用四条程序:PC0x100的store晚到槽4=17,PC0x104的load读4,后面的store与load传播 2*v1+1。第一次SSIT为空,模式与盲猜一样:load先读3,第6轮发现冲突,重放I1–I3,并学习

text
SSIT[0x100] = 0
SSIT[0x104] = 0

重新运行同一个程序,初始扫描在集合0的LFST放I0,让I1等I0。第1轮I1地址已知也不执行;第6轮I0地址和数据齐全、标DONE,I1才从它转发17。I2接着产生35,I3得到35,不发生重放。

实验 重放次数 实际load执行数 完成轮数
空历史第一次运行 1 4 10
保留SSIT再次运行 0 2 10
清空历史后再运行 1 4 10

轮数相同并不否定少做两次load的事实,也不允许宣称已经测出加速。这里老store始终压住退休,教学阶段安排让三种情况都在第10轮结束。

再保持两个PC不变,只让I0这次写槽9,I1仍读槽4。学到的集合仍让I1等I0,但实际地址已不冲突,正确load值是3,后续值为7。这是假依赖:结果正确,等待却不必要。参考器输出5次 predicted-store 等待尝试;该计数是驱动访问候选时记录的尝试次数,不等于5条不同load,更不是硬件停顿周期的普遍定义。

合并两个集合,然后检查LFST生命周期 ​

先训练两对PC:store A=0x300与load X=0x304组成集合0;store B=0x308与load Y=0x30c组成集合1。再训练A与Y,四个PC立即都属于0。

新窗口按程序序是S0(A)、S1(B)、L2(X)。初始前驱表为 [无,0,1],LFST[0]=1。即使S1地址和数据先到,也不能先标DONE,因为它还等S0。

S0完成时,LFST仍指向1,必须保留。接着S1完成,才因“表项仍是我”清掉LFST。L2等到S1完成后执行真实地址查询;它不会把“等的是S1”误当成“必须从S1拿数据”。本例L2读槽2,S0、S1分别写0、1,所以最终还是读内存槽2的初值0。

这个例子把三个身份分开:集合号0表示预测分组,前驱1表示调度等待者,实际来源−1表示读已提交内存。三者混用会把一个性能建议变成错误的数据路由。

训练与恢复同时发生时怎么办 ​

违例load及年轻后缀已经由底层取消;更老store仍保留。本文完成PC集合合并后,重新扫描所有活跃未完成项,重建它们的链和LFST。已经完成的项不被追溯地标成“尚未完成”,新加的等待边只约束还没执行或完成的工作。

如果不重建,LFST可能仍指向被取消的代次,或两个刚合并的组各有一条旧链却只剩一个表项。本页用 O(n) 扫描避开这类悬空身份和链覆盖问题。真实窄带硬件通常需要其他恢复结构,不能把这个全窗口扫描当成无成本的组合电路。

显式清历史也会清SSIT并重建当前等待边;它可以让load更早猜测,之后仍靠独立检测兜底。清表没有清架构内存,也不取消已经正确退休的结果。外部调用者不应绕开窗口直接改正在使用的SSIT。

推论与应用

等待链的性质与安全底线 ​

每次建立前驱时,LFST只保存扫描中已经经过的store,所以前驱年龄严格小于当前年龄。无论是预测边还是原本load结果的真实数据依赖,都指向更老生产者。由年龄严格递减,等待图不可能形成环。

在一次重建之后,固定一个集合。当时仍未完成的store按年龄形成一条链;一条load只需等链中它之前的最后store。沿链归纳,最后者DONE时,所有更老链成员也已DONE;已经在重建前完成的store本来就具备字段。于是这个等待完成条件确实覆盖该集合中的相关在途store,而不必给load保存整组动态前驱。

若期间出现新冲突合并或恢复,旧链不被假定仍完整,协议重新建链。即使某个load早已执行而未受新约束,它的错误仍由地址/来源检测发现并恢复。预测器不能删除这道检查:空历史、清表、新路径和变化的地址模式都可能让它漏掉真实依赖。

因此一般正确性来自重放页的退休前缀证明。这里加入的等待只会限制执行许可,不会改变真实来源选择或架构提交值;在有限驱动与持续调度下,严格年龄方向也不会给最老项增加一个年轻阻塞者。训练后未见重放只是一次运行的事实,不是任何输入都不会再违例的定理。

成本和更接近硬件的取舍 ​

设历史表有p个不同PC,窗口n项、k个活动集合。普通完整PC查表和LFST访问在散列表均摊常数模型下计费;训练同组或加入一个新成员为均摊O(1)。合并两个已有集合要扫描全部p个PC,最坏O(p),随后重建链O(n)。历史表占O(p),LFST至多O(min(k,n)),每项另存一个前驱年龄。

这不是原论文无tag定长SSIT的容量模型。完整键避免PC索引冲突,但历史可增长;全表合并更直接,却没有固定表更新的低成本。若改成哈希槽、有限集合号、周期清除或置信计数,必须重新说明别名、替换和动态身份恢复。原论文研究过这些取舍,并不提供“任意工作负载都接近最优”的保证。[1, §6]

公开执行器仍承担前两页的队列扫描和排序;若发生r次训练恢复,集合与重建额外总代价可保守写为 O(∑t=1r(pt+n))。日志中排序输出SSIT、保存取消列表和全状态均另有费用。PC、年龄、代次和整数值若不能装入一个机器字,还需按位成本计费。

可执行终点要求交付实际SSIT、LFST和前驱表,重新运行冷/热/变址/清表四种条件,并保留来源查询与退休证据。学到了哪些关系、这次等了谁、最终读了谁的值,应在答案里分别可见。

参考资料
  1. George Z. Chrysos、Joel S. Emer,Memory Dependence Prediction using Store Sets,ISCA1998,pp.142–153;§5.1定义历史冲突集合,§6.1给SSIT/LFST与同集合store链、完成时条件清除和恢复,§6.2讨论局部逐步合并,§§6.3–6.4讨论清表、无tag别名与容量。本文完整键与全表立即合并是明确不同的可执行教学变体。
  2. Berkeley Out-of-Order Machine,The Load/Store Unit,官方文档,访问于2026-10-10,Memory Ordering Failures。用于说明预测之外仍需实际地址检查和恢复;本文不声称BOOM使用本页这张Store Set表。
关系图谱3 个相邻概念 · 1 类关系

拖动节点调整位置。

显示关系

显示:依赖

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