你害怕以指数方式填充机器是对的,但你低估了它的力量。一个常见的经验法则是,您可以期望在动态代码中平均有约 20% 的分支。这意味着每 5 条指令中有一个分支。今天的大多数 CPU 都有一个深度乱序内核,可以提前获取并执行数百条指令——以 Intel 的 Haswell 为例,它有192 个条目 ROB,这意味着您最多可以保存 4 个级别的分支(此时您'将有 16 个“前沿”和 31 个“块”,每个包括一个分叉分支 - 假设每个块将有 5 条指令,您几乎已经填满了 ROB,并且另一个级别会超过它)。那时你只会进步到大约 20 条指令的有效深度,
如果您想在 3 级分支上发散,这意味着您将没有 8 个并行上下文,每个上下文只有 24 个条目可用于提前运行。即使那只是当您忽略回滚 7/8 工作的开销,需要复制所有保存状态的硬件(如寄存器,您有几十个),以及需要像您一样将其他资源拆分为 8 个部分时用ROB做了。此外,这还不包括必须管理复杂的版本控制、转发、一致性等的内存管理。
忘记功耗,即使您可以支持这种浪费的并行性,在您可以在每条路径上推进多个指令之前,将您的资源分散到如此薄的程度实际上会让您窒息。
现在,让我们来看看在单个分支上拆分的更合理的选择——这开始看起来像超线程——你在 2 个上下文中拆分/共享你的核心资源。此功能具有一些性能优势,这是理所当然的,但这只是因为这两个上下文都是非推测性的。事实上,我相信根据工作负载组合(此处AnandTech 的评论中的数字),一个接一个地运行 2 个上下文的常见估计约为 10-30% - 如果您确实打算同时运行这两个上下文,那就太好了一个接一个的任务,但不是当你要扔掉其中一个的结果时。即使您忽略此处的模式切换开销,您也会获得 30% 的收益,而只会损失 50% - 这没有任何意义。
另一方面,您可以选择预测分支(今天的现代预测器平均可以达到超过 95% 的成功率),并支付错误预测的惩罚,这已经被乱序引擎部分隐藏(有些分支之前的指令可能会在它被清除后执行,大多数 OOO 机器都支持)。这使得任何深度乱序引擎都可以自由漫游,推测其全部潜在深度,并且大部分时间都是正确的。此处冲洗某些工作的几率确实呈几何级数下降(第一个分支后为 95%,第二个分支后约为 90%,等等),但冲洗惩罚也降低了。它仍然远优于 1/n 的全局效率(对于 n 级分叉)。