【问题标题】:Return stack buffer?返回堆栈缓冲区?
【发布时间】:2012-11-23 06:16:16
【问题描述】:

据我了解,返回堆栈缓冲区仅支持 4 到 16 个条目(来自 wiki:http://en.wikipedia.org/wiki/Branch_predictor#Prediction_of_function_returns),并且不是键值对(基于 ret 指令的位置索引)。这是真的吗? 当上下文切换发生时,RSB 会发生什么?

假设我们在返回堆栈缓冲区长度为 16 的 CPU 中处理了 50 个未返回的函数,之后会发生什么?这是否意味着所有预测都失败了?你能举例说明吗?这种场景在递归函数调用中是否相同?

【问题讨论】:

  • 我认为,返回堆栈缓冲区在上下文切换时被重置。 Agner 的 pdf 中有一些关于 RSB 的信息:agner.org/optimize/microarchitecture.pdf 第 3.14 节。 RSB 是一个固定长度的 LIFO 缓冲区(后进先出;也称为堆栈);在深层调用堆栈中,较旧的返回从 RSB 中推出,并且无法预测。这种技术在深度递归的情况下几乎没有帮助。 PS。在第 3.1 节最后一点中,Agner 说“预测器收集的信息经常由于任务切换和其他上下文切换而丢失”
  • 据我了解,RSB 不知道上下文切换:就像 osgx 说它是一个 LIFO 缓冲区,在上下文切换时会出现“错误”和错误预测,就像不匹配的 CALL 或 RET遇到过。
  • 非常频繁的调用/返回的最常见情况对于 16 项“堆栈”来说足够浅,尽管较新的 CPU 确实使其更深一些。 (如果 RSB 为空,有些会退回到标准的间接分支预测。)

标签: x86 cpu cpu-architecture branch-prediction micro-architecture


【解决方案1】:

BPU 可以包含自己的 RAS 预测器,当它预测 BTB 中的调用类型时,它将假定的调用 NLIP(以下指令的 IP)推送到 RAS 堆栈。它在 BTB 中预测的下一次返回将使用 RAS 的顶部作为预测地址(就像当它预测常规间接分支时,ITA 中的并行命中将超过 BTB 中的目标地址)。

BAC 将在解码时通过将每个调用指令的 NLIP 推送到其自己的 RSB 来验证/覆盖这些返回目标预测,下一个返回地址的预测将与该地址进行比较。如果不正确,BAC 将发出 BAclear 并在管道开始时将下一个 IP 逻辑重新引导到正确的返回地址(如果 RSB 损坏,这可能会被证明是错误的)。它可能会用 BAC RSB 状态覆盖 RAS 预测器堆栈。

在一个实现中,BAC 向 TOS 指针提供它验证的每个分支预测,以及落入地址。一旦执行了分支并且知道了实际结果,如果发生错误预测,则恢复 RSB TOS。我认为更有效的是在退休时拥有一个架构 RSB,它在管道刷新/错误预测时被复制到 BAC RSB 和 RAS 预测器中。这可以防止恢复到损坏的 RSB。

RAS 预测器可能是一个循环堆栈,根据实现,它可能有也可能没有溢出和下溢检查和保证。当堆栈已满时,一个新的预测可能会覆盖最旧的预测,以便它始终是最新的(而不是阻止它在已满时添加,这意味着保留一个计数器来确定有多少调用/返回它无法进行预测为了)。至于下溢,它可能拒绝做出预测,而是使用 ITA 进行预测。如果 RSB 下溢,它可能不会覆盖 RAS 预测器所做的预测。

上下文切换的硬件中断会导致在执行宏操作的最终微操作时清除流水线。 RSB 很可能恢复到架构状态以在中断后继续。预测器 RAS / BAC RSB 可能会在微码中被刷新,如果它被损坏,它最终会自行恢复。

【讨论】:

  • @PeterCordes 是的,但是在 BPU 进行早期预测的阶段,预测的调用指令的长度是未知的。它必须在 BTB 条目中指示,以便在解码或退出时由 BTB 更新调用
  • 哦,我明白了。我们确定前端(通过 RSB)可以在相应的调用被完全解码之前预测一个 ret 吗?假设是,是否有任何证据表明如果call 有前缀或者很难知道正确的长度,这可能会错误预测(或需要重新引导或其他东西)?
猜你喜欢
  • 2014-04-21
  • 1970-01-01
  • 2017-02-23
  • 1970-01-01
  • 1970-01-01
  • 2015-04-08
  • 2010-11-29
  • 2015-07-03
  • 1970-01-01
相关资源
最近更新 更多