为什么不只预测两个分支?

Why not just predict both branches?

CPU 使用分支预测来加速代码,但前提是实际采用了第一个分支。

为什么不简单地选择两个分支?也就是说,假设两个分支都将被命中,缓存两侧,并在必要时采用正确的分支。缓存不需要失效。虽然这需要编译器预先加载两个分支(更多内存、适当的布局等),但我认为适当的优化可以简化这两个分支,以便可以从单个预测器获得接近最佳的结果。也就是说,一个人需要更多的内存来加载两个分支(对于 N 个分支来说是指数级的),大多数时候应该能够 "recache" 失败的分支在完成执行之前足够快地使用新代码已采取分支。

if (x) Bl 否则 Br;

不假设Bl被采用,而是假设Bl和Br都被采用(某种类型的并行处理或特殊交错)并且在实际确定分支之后,一个分支然后无效并且然后可以释放缓存使用(可能需要某种特殊技术才能正确填充和使用)。

事实上,不需要预测电路,所有用于预测电路的设计都可以用于处理两个分支。

如果这可行,有什么想法吗?

从两个路径获取指令的历史视角

第一个类似的提案(据我所知)在 this 1968 年的专利中进行了讨论。我知道您只是询问有关从两个分支获取指令的问题,但请稍等一下。在该专利中,列出了三种广泛的策略,其中之一是遵循两条路径(fall-through 路径和分支路径)。也就是说,不仅从两条路径中获取指令,而且还执行两条路径。当条件分支指令被解析时,其中一个路径被丢弃。在专利的介绍中只是作为一个想法被提及,但专利本身是关于另一项发明。

1977 年晚些时候,IBM 发布了一个商业处理器,称为 IBM 3033 processor. That is the first processor (to my knowledge) to implement exactly what you are proposing. I'm surprised to see that the Wikipedia page did not mention that the processor fetched instructions from both paths. The paper that describes the IBM 3033 is titled "The IBM 3033: An inside look". Unfortunately, I'm not able to find the paper. But the paper on the IBM 3090 确实提到了这一事实。所以你提出的建议确实有道理,并且大约五年前就在真正的处理器中实现了。

专利于 1981 年提交,并于 1984 年获得批准,涉及具有两个存储器的处理器,并且可以同时从两个存储器中获取指令。我引用专利摘要:

A dual fetch microsequencer having two single-ported microprogram memories wherein both the sequential and jump address microinstructions of a binary conditional branch can be simultaneously prefetched, one from each memory. The microprogram is assembled so that the sequential and jump addresses of each branch have opposite odd/even polarities. Accordingly, with all odd addresses in one memory and even in the other, the first instruction of both possible paths can always be prefetched simultaneously. When a conditional branch microinstruction is loaded into the execution register, its jump address or a value corresponding to it is transferred to the address register for the appropriate microprogram memory. The address of the microinstruction in the execution register is incremented and transferred to the address register of the other microprogram memory. Prefetch delays are thereby reduced. Also, when a valid conditional jump address is not provided, that microprogram memory may be transparently overlayed during that microcycle.

从两个路径获取和执行指令的历史视角

在 80 年代和 90 年代发表了许多关于提出和评估技术的研究,通过这些技术不仅可以获取而且还可以执行来自两条路径的指令,即使对于多个条件分支也是如此。这将有潜在的额外 overhead of fetching data required by both paths. The idea of branch prediction confidence was proposed in this paper in 1996 and was used to improve such techniques by being more selective regarding which paths to fetch and execute. Another paper (Threaded Multiple Path Execution) published in 1998 proposes an architecture that exploits simultaneous multithreading (SMT) to run multiple paths following conditional branches. Another paper(双路径指令处理)于 2002 年发布,建议从两条路径获取、解码和重命名但不执行指令。

讨论

从两条路径中获取指令到一个或多个高速缓存中通常会降低高速缓存的有效容量,因为通常情况下,其中一条路径的执行频率会比另一条路径高得多(在某些情况下,可能高度不规则、图案)。想象一下取入 L3 缓存,它实际上总是在所有内核之间共享并保存指令和数据。这会对 L3 缓存保存有用数据的能力产生负面影响。取入更小的 L2 缓存甚至会导致性能大幅下降,尤其是当包含 L3 时。从所有内核的多个条件分支的两条路径获取指令可能会导致高速缓存中保存的热数据被频繁驱逐和带回。因此,您提出的技术的极端变体会降低现代架构的整体性能。然而,攻击性较低的变体可能是有益的。

我不知道有任何真正的现代处理器在看到条件分支时会在两条路径上获取指令(也许有些会这样做,但没有公开披露)。但是指令预取已经被广泛研究并且仍然是。这里需要解决的一个重要问题是:当预测路径被证明是错误路径时,来自另一条路径的足够数量的指令已经存在于缓存中的概率是多少?如果概率很高,那么就没有从两条路径获取指令的动机。否则,确实有机会。根据 Intel 的旧 paper(Wrong-Path 指令预取),在测试的基准测试中,超过 50% 在错误预测路径上访问的指令后来在正确路径执行期间被访问。这个问题的答案当然取决于正在设计的处理器的目标域。