为什么要预测分支,而不是简单地并行执行?

mcz*_*nek 3 cpu-architecture branch-prediction

我相信在创建CPU时,当选择错误的分支时,分支预测是一个主要的减速.那么为什么CPU设计师选择一个分支而不是简单地执行两个分支,然后一旦你知道哪一个被选中就切掉一个?

我意识到这只能在短数量的指令中深入2或3个分支,或者并行阶段的数量会变得非常大,所以在某些时候你仍然需要一些分支预测,因为你肯定会遇到更大的分支,但是不会像这样的几个阶段有意义吗?在我看来,它会显着加快速度,值得增加一点复杂性.

即使只是一个分支深度几乎有一半的时间被错误的分支吃掉,对吧?

或者它可能已经有点像这样?当您进行组装时,分支通常只在两种选择中进行选择,对吗?

Lee*_*eor 6

你是害怕以指数​​方式填充机器,但是你低估了它的力量.一个常见的经验法则表示,您可以在动态代码中平均拥有约20%的分支.这意味着每5个指令中有一个分支.今天大多数CPU都有一个深度无序核心,可以提取并执行数百条指令 - 例如,它使用Intels的Haswell,它有192个条目ROB,这意味着你最多可以保存4个级别的分支(此时你将有16个"前线"和31个"块",每个包括一个分叉分支 - 假设每个块将有5个指令,你几乎填满你的ROB,而另一个级别将超过它).此时,您将只进行到约20条指令的有效深度,使得任何指令级并行都无用.

如果你想在3个级别的分支上分歧,这意味着你将有8个并行上下文,每个只有24个条目可用于提前运行.即使只是当你忽略了回滚7/8工作的开销时,需要复制所有状态保存的HW(比如寄存器,你有几十个),并且需要将其他资源分成8个部分,比如你做了ROB.此外,这还不包括内存管理,它必须管理复杂的版本控制,转发,一致性等.

忘记功耗,即使你可以支持那种浪费的并行性,在你可以在每条路径上推进超过几条指令之前,扩展你的资源就会让你感到窒息.

现在,让我们来看一下在单个分支上拆分的更合理的选择 - 这开始看起来像超线程 - 你在2个上下文中分割/共享你的核心资源.此功能具有一些性能优势,但仅限于两个上下文都是非推测性的.事实上,我认为相比于工作负载组合(AnandTech 在这里审查的数字),常见估计比一个接一个地运行2个上下文大约10-30%- 如果你确实打算同时运行两个,那就太好了一个接一个的任务,但不是当你要扔掉其中一个的结果时.即使你忽略了这里的模式切换开销,你也只能获得30%的损失50% - 没有任何意义.

另一方面,您可以选择预测分支(今天的现代预测变量平均可以达到95%以上的成功率),并支付误预测的惩罚,这已被无序引擎部分隐藏(一些在分支之前的指令可以在清除之后执行,大多数OOO机器都支持该指令.这使得任何深度无序引擎都可以自由地向前漫游,推测其完全潜在的深度,并且大部分时间是正确的.冲刷这里的一些工作的几率确实在几何上减少(第一个分支后为95%,第二个分支后为~90%等),但冲洗罚分也会减少.它仍然远远好于1/n的全局效率(对于n级分叉).