如何取消分支预测?

时间:2017-02-10 20:24:24

标签: c cpu-architecture branch-prediction

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

第一句话:

  

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

第二句:

  

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

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

  

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

让我最震惊的是:

  

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

为什么要使用分支预测?

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

2 个答案:

答案 0 :(得分:8)

  

查看分支预测是否实际上减慢了我的程序或帮助

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

如果分支预测不存在,所有分支都会像错误预测分支一样昂贵。

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

  
    

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

  
     

为什么要使用分支预测?

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

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

  

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

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

  

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

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

答案 1 :(得分:5)

现代处理器具有管道,允许CPU以比其他方式更快的速度工作。这是一种并行形式,它在实际需要指令之前几个时钟周期开始处理指令。有关详细信息,请参阅此处here

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

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

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

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