如何取消分支预测?

Ton*_*ous 5 c cpu-architecture branch-prediction

从阅读本文开始,我看到了接下来的两个引号:

第一个引用:

不可预测的分支行为的典型情况是比较结果取决于数据.

第二个引用:

没有分支意味着没有错误的预测

对于我的项目,我处理依赖数据,并执行许多ifswitch语句.我的项目与之相关,Big Data因此必须尽可能高效.所以我想对用户提供的数据进行测试,看看分支预测是否会减慢我的程序或帮助.从阅读这里:

误预测延迟在10到20个时钟周期之间.

让我最震惊的是:

删除分支不仅可以提高代码的运行时性能,还可以帮助编译器优化代码.

为什么要使用分支预测?

有没有办法强制编译器生成没有分支的汇编代码?或者禁用分支预测以便CPU?所以我可以比较两个结果?

sep*_*p2k 8

看看分支预测是否真的会减慢我的程序或帮助

分支预测不会减慢程序的速度.当人们谈论错过预测的成本时,他们谈论的是错误预测的分支与正确预测的分支相比要多得多.

如果不存在分支预测,则所有分支都将与错误预测分支一样昂贵.

那么"错误预测延迟在10到20个时钟周期之间"真正意味着成功的分支预测可以节省10到20个周期.

删除分支不仅可以提高代码的运行时性能,还可以帮助编译器优化代码.

为什么要使用分支预测?

为什么使用分支预测去除分支?你不应该.如果编译器可以删除分支,它将(假设已启用优化),并且如果程序员可以删除分支(假设它不会损害可读性或者它是一个性能关键的代码段),它们应该.

这几乎不会使分支预测无用.即使您从程序中删除尽可能多的分支,它仍将包含许多分支.因此,由于这一点并且因为不可预测的分支有多么昂贵,分支预测对于良好的性能至关重要.

有没有办法强制编译器生成没有分支的汇编代码?

优化编译器已经可以在程序中删除分支(不改变程序的语义),但是,除非我们讨论的是一个非常简单的int main() {return 0;}程序,否则不可能删除所有分支.循环需要分支(除非它们已展开,但只有在您提前知道迭代次数时才有效),大多数if-和switch-语句也是如此.如果你可以最小化你的程序中的ifs,switches和循环的数量,那很好,但你将无法删除所有这些.

或者禁用分支预测以便CPU?所以我可以比较两个结果?

据我所知,不可能在x86或x86-64 CPU上禁用分支预测.正如我所说,这永远不会提高性能(虽然它可能使其可预测,但在使用这些CPU的上下文中通常不是必需的).


dor*_*ron 5

现代处理器具有管道,允许CPU以比其他方式更快的速度工作.这是一种并行形式,它在实际需要指令之前几个时钟周期开始处理指令.看到这里这里了解更多详情.

这很有效,直到我们到达分支.由于我们正在跳跃,管道中的工作已不再相关.然后CPU需要刷新管道并重新启动.这导致延迟几个时钟周期,直到管道再次满.这被称为管道失速.

现代CPU非常聪明,当填充管道时无条件跳转跟随跳转,从而防止失速.这在分支时不起作用,因为CPU不知道跳转的确切位置.

分支预测尝试通过猜测CPU在完全评估跳转之前将遵循哪个分支来解决此问题.这(当它工作时)防止失速.

由于几乎所有编程都涉及决策,因此分支是不可避免的.但是,当然可以编写具有较少分支的代码,从而减少由错误预测引起的延迟.一旦我们进行分支,分支预测至少可以让我们有机会做正确的事情并且没有CPU管道停顿.

  • 一个小的挑剔:即使是无条件的跳跃也可能是有问题的,因为它们可以是变量(想想MIPS`jar`)或间接的(例如x86`jmp [rbx]`). (2认同)